aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins.cc5
-rw-r--r--gcc/config/aarch64/aarch64-sve.md64
-rw-r--r--gcc/config/aarch64/aarch64-sve2.md16
-rw-r--r--gcc/config/aarch64/iterators.md6
-rw-r--r--gcc/config/arm/arm.cc5
-rw-r--r--gcc/config/arm/arm.md13
-rw-r--r--gcc/config/arm/thumb1.md9
-rw-r--r--gcc/config/arm/thumb2.md21
-rw-r--r--gcc/doc/tm.texi10
-rw-r--r--gcc/doc/tm.texi.in10
-rw-r--r--gcc/testsuite/c-c++-common/asan/pr121389-1.c23
-rw-r--r--gcc/testsuite/c-c++-common/asan/pr121389-2.c37
-rw-r--r--gcc/testsuite/c-c++-common/asan/pr121389-3.c130
-rw-r--r--gcc/testsuite/c-c++-common/asan/pr121389-4.c6
-rw-r--r--gcc/testsuite/g++.target/aarch64/sve/pr121449.C44
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr120986-1.c10
-rw-r--r--gcc/testsuite/gcc.target/aarch64/torture/pr120986-2.c7
-rw-r--r--gcc/testsuite/gcc.target/arm/cmse/cmse-18.c7
-rw-r--r--gcc/testsuite/gcc.target/arm/cmse/cmse-19.c14
-rw-r--r--gcc/tree-ssa-sccvn.cc27
-rw-r--r--gcc/tree-tailcall.cc207
-rw-r--r--gcc/tree-vect-loop.cc172
-rw-r--r--gcc/tree-vect-stmts.cc15
23 files changed, 558 insertions, 300 deletions
diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
index e394c9a..1764cf8 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
@@ -4590,8 +4590,9 @@ function_expander::expand ()
{
/* The last element of these functions is always an fpm_t that must be
written to FPMR before the call to the instruction itself. */
- gcc_assert (args.last ()->mode == DImode);
- emit_move_insn (gen_rtx_REG (DImode, FPM_REGNUM), args.last ());
+ rtx fpm = args.last ();
+ gcc_assert (CONST_INT_P (fpm) || GET_MODE (fpm) == DImode);
+ emit_move_insn (gen_rtx_REG (DImode, FPM_REGNUM), fpm);
}
rtx result = base->expand (*this);
if (function_returns_void_p ())
diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md
index 88d323a..51e2d7d 100644
--- a/gcc/config/aarch64/aarch64-sve.md
+++ b/gcc/config/aarch64/aarch64-sve.md
@@ -1542,18 +1542,18 @@
UNSPEC_LD1_GATHER))]
"TARGET_SVE && TARGET_NON_STREAMING"
{@ [cons: =0, 1, 2, 3, 4, 5 ]
- [&w, Z, w, Ui1, Ui1, Upl] ld1<Vesize>\t%0.s, %5/z, [%2.s]
- [?w, Z, 0, Ui1, Ui1, Upl] ^
- [&w, vgw, w, Ui1, Ui1, Upl] ld1<Vesize>\t%0.s, %5/z, [%2.s, #%1]
- [?w, vgw, 0, Ui1, Ui1, Upl] ^
- [&w, rk, w, Z, Ui1, Upl] ld1<Vesize>\t%0.s, %5/z, [%1, %2.s, sxtw]
- [?w, rk, 0, Z, Ui1, Upl] ^
- [&w, rk, w, Ui1, Ui1, Upl] ld1<Vesize>\t%0.s, %5/z, [%1, %2.s, uxtw]
- [?w, rk, 0, Ui1, Ui1, Upl] ^
- [&w, rk, w, Z, i, Upl] ld1<Vesize>\t%0.s, %5/z, [%1, %2.s, sxtw %p4]
- [?w, rk, 0, Z, i, Upl] ^
- [&w, rk, w, Ui1, i, Upl] ld1<Vesize>\t%0.s, %5/z, [%1, %2.s, uxtw %p4]
- [?w, rk, 0, Ui1, i, Upl] ^
+ [&w, Z, w, Ui1, Ui1, Upl] ld1<Vesize>\t%0.s, %5/z, [%2.s]
+ [?w, Z, 0, Ui1, Ui1, Upl] ^
+ [&w, vg<Vesize>, w, Ui1, Ui1, Upl] ld1<Vesize>\t%0.s, %5/z, [%2.s, #%1]
+ [?w, vg<Vesize>, 0, Ui1, Ui1, Upl] ^
+ [&w, rk, w, Z, Ui1, Upl] ld1<Vesize>\t%0.s, %5/z, [%1, %2.s, sxtw]
+ [?w, rk, 0, Z, Ui1, Upl] ^
+ [&w, rk, w, Ui1, Ui1, Upl] ld1<Vesize>\t%0.s, %5/z, [%1, %2.s, uxtw]
+ [?w, rk, 0, Ui1, Ui1, Upl] ^
+ [&w, rk, w, Z, i, Upl] ld1<Vesize>\t%0.s, %5/z, [%1, %2.s, sxtw %p4]
+ [?w, rk, 0, Z, i, Upl] ^
+ [&w, rk, w, Ui1, i, Upl] ld1<Vesize>\t%0.s, %5/z, [%1, %2.s, uxtw %p4]
+ [?w, rk, 0, Ui1, i, Upl] ^
}
)
@@ -1572,14 +1572,14 @@
UNSPEC_LD1_GATHER))]
"TARGET_SVE && TARGET_NON_STREAMING"
{@ [cons: =0, 1, 2, 3, 4, 5]
- [&w, Z, w, i, Ui1, Upl] ld1<Vesize>\t%0.d, %5/z, [%2.d]
- [?w, Z, 0, i, Ui1, Upl] ^
- [&w, vgd, w, i, Ui1, Upl] ld1<Vesize>\t%0.d, %5/z, [%2.d, #%1]
- [?w, vgd, 0, i, Ui1, Upl] ^
- [&w, rk, w, i, Ui1, Upl] ld1<Vesize>\t%0.d, %5/z, [%1, %2.d]
- [?w, rk, 0, i, Ui1, Upl] ^
- [&w, rk, w, i, i, Upl] ld1<Vesize>\t%0.d, %5/z, [%1, %2.d, lsl %p4]
- [?w, rk, 0, i, i, Upl] ^
+ [&w, Z, w, i, Ui1, Upl] ld1<Vesize>\t%0.d, %5/z, [%2.d]
+ [?w, Z, 0, i, Ui1, Upl] ^
+ [&w, vg<Vesize>, w, i, Ui1, Upl] ld1<Vesize>\t%0.d, %5/z, [%2.d, #%1]
+ [?w, vg<Vesize>, 0, i, Ui1, Upl] ^
+ [&w, rk, w, i, Ui1, Upl] ld1<Vesize>\t%0.d, %5/z, [%1, %2.d]
+ [?w, rk, 0, i, Ui1, Upl] ^
+ [&w, rk, w, i, i, Upl] ld1<Vesize>\t%0.d, %5/z, [%1, %2.d, lsl %p4]
+ [?w, rk, 0, i, i, Upl] ^
}
)
@@ -2488,13 +2488,13 @@
(match_operand:SVE_4 4 "register_operand")]
UNSPEC_ST1_SCATTER))]
"TARGET_SVE && TARGET_NON_STREAMING"
- {@ [ cons: 0 , 1 , 2 , 3 , 4 , 5 ]
- [ Z , w , Ui1 , Ui1 , w , Upl ] st1<Vesize>\t%4.s, %5, [%1.s]
- [ vgw , w , Ui1 , Ui1 , w , Upl ] st1<Vesize>\t%4.s, %5, [%1.s, #%0]
- [ rk , w , Z , Ui1 , w , Upl ] st1<Vesize>\t%4.s, %5, [%0, %1.s, sxtw]
- [ rk , w , Ui1 , Ui1 , w , Upl ] st1<Vesize>\t%4.s, %5, [%0, %1.s, uxtw]
- [ rk , w , Z , i , w , Upl ] st1<Vesize>\t%4.s, %5, [%0, %1.s, sxtw %p3]
- [ rk , w , Ui1 , i , w , Upl ] st1<Vesize>\t%4.s, %5, [%0, %1.s, uxtw %p3]
+ {@ [ cons: 0 , 1 , 2 , 3 , 4 , 5 ]
+ [ Z , w , Ui1 , Ui1 , w , Upl ] st1<Vesize>\t%4.s, %5, [%1.s]
+ [ vg<Vesize> , w , Ui1 , Ui1 , w , Upl ] st1<Vesize>\t%4.s, %5, [%1.s, #%0]
+ [ rk , w , Z , Ui1 , w , Upl ] st1<Vesize>\t%4.s, %5, [%0, %1.s, sxtw]
+ [ rk , w , Ui1 , Ui1 , w , Upl ] st1<Vesize>\t%4.s, %5, [%0, %1.s, uxtw]
+ [ rk , w , Z , i , w , Upl ] st1<Vesize>\t%4.s, %5, [%0, %1.s, sxtw %p3]
+ [ rk , w , Ui1 , i , w , Upl ] st1<Vesize>\t%4.s, %5, [%0, %1.s, uxtw %p3]
}
)
@@ -2511,11 +2511,11 @@
(match_operand:SVE_2 4 "register_operand")]
UNSPEC_ST1_SCATTER))]
"TARGET_SVE && TARGET_NON_STREAMING"
- {@ [ cons: 0 , 1 , 3 , 4 , 5 ]
- [ Z , w , Ui1 , w , Upl ] st1<Vesize>\t%4.d, %5, [%1.d]
- [ vgd , w , Ui1 , w , Upl ] st1<Vesize>\t%4.d, %5, [%1.d, #%0]
- [ rk , w , Ui1 , w , Upl ] st1<Vesize>\t%4.d, %5, [%0, %1.d]
- [ rk , w , i , w , Upl ] st1<Vesize>\t%4.d, %5, [%0, %1.d, lsl %p3]
+ {@ [ cons: 0 , 1 , 3 , 4 , 5 ]
+ [ Z , w , Ui1 , w , Upl ] st1<Vesize>\t%4.d, %5, [%1.d]
+ [ vg<Vesize> , w , Ui1 , w , Upl ] st1<Vesize>\t%4.d, %5, [%1.d, #%0]
+ [ rk , w , Ui1 , w , Upl ] st1<Vesize>\t%4.d, %5, [%0, %1.d]
+ [ rk , w , i , w , Upl ] st1<Vesize>\t%4.d, %5, [%0, %1.d, lsl %p3]
}
)
diff --git a/gcc/config/aarch64/aarch64-sve2.md b/gcc/config/aarch64/aarch64-sve2.md
index a4c3257..a3cbbce 100644
--- a/gcc/config/aarch64/aarch64-sve2.md
+++ b/gcc/config/aarch64/aarch64-sve2.md
@@ -2211,14 +2211,14 @@
;; - FDOT (2-way, indexed) (FP8DOT2)
;; -------------------------------------------------------------------------
(define_insn "@aarch64_sve_dot<mode>"
- [(set (match_operand:SVE_FULL_HSF 0 "register_operand")
- (unspec:SVE_FULL_HSF
- [(match_operand:SVE_FULL_HSF 1 "register_operand")
+ [(set (match_operand:SVE_FULL_HSF_FP8_FDOT 0 "register_operand")
+ (unspec:SVE_FULL_HSF_FP8_FDOT
+ [(match_operand:SVE_FULL_HSF_FP8_FDOT 1 "register_operand")
(match_operand:VNx16QI 2 "register_operand")
(match_operand:VNx16QI 3 "register_operand")
(reg:DI FPM_REGNUM)]
UNSPEC_DOT_FP8))]
- "TARGET_SSVE_FP8DOT4 && !(<MODE>mode == VNx8HFmode && !TARGET_SSVE_FP8DOT2)"
+ ""
{@ [ cons: =0 , 1 , 2 , 3 ; attrs: movprfx ]
[ w , 0 , w , w ; * ] fdot\t%0.<Vetype>, %2.b, %3.b
[ ?&w , w , w , w ; yes ] movprfx\t%0, %1\;fdot\t%0.<Vetype>, %2.b, %3.b
@@ -2226,15 +2226,15 @@
)
(define_insn "@aarch64_sve_dot_lane<mode>"
- [(set (match_operand:SVE_FULL_HSF 0 "register_operand")
- (unspec:SVE_FULL_HSF
- [(match_operand:SVE_FULL_HSF 1 "register_operand")
+ [(set (match_operand:SVE_FULL_HSF_FP8_FDOT 0 "register_operand")
+ (unspec:SVE_FULL_HSF_FP8_FDOT
+ [(match_operand:SVE_FULL_HSF_FP8_FDOT 1 "register_operand")
(match_operand:VNx16QI 2 "register_operand")
(match_operand:VNx16QI 3 "register_operand")
(match_operand:SI 4 "const_int_operand")
(reg:DI FPM_REGNUM)]
UNSPEC_DOT_LANE_FP8))]
- "TARGET_SSVE_FP8DOT4 && !(<MODE>mode == VNx8HFmode && !TARGET_SSVE_FP8DOT2)"
+ ""
{@ [ cons: =0 , 1 , 2 , 3 ; attrs: movprfx ]
[ w , 0 , w , y ; * ] fdot\t%0.<Vetype>, %2.b, %3.b[%4]
[ ?&w , w , w , y ; yes ] movprfx\t%0, %1\;fdot\t%0.<Vetype>, %2.b, %3.b[%4]
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 8f8237e..68b080d 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -543,6 +543,12 @@
;; elements.
(define_mode_iterator SVE_FULL_HSF [VNx8HF VNx4SF])
+;; Like SVE_FULL_HSF, but selectively enables those modes that are valid
+;; for the variant of the SVE2 FP8 FDOT instruction associated with that
+;; mode.
+(define_mode_iterator SVE_FULL_HSF_FP8_FDOT [(VNx4SF "TARGET_SSVE_FP8DOT4")
+ (VNx8HF "TARGET_SSVE_FP8DOT2")])
+
;; Partial SVE floating-point vector modes that have 16-bit or 32-bit
;; elements.
(define_mode_iterator SVE_PARTIAL_HSF [VNx2HF VNx4HF VNx2SF])
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 29b45ae..8b951f3 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -18983,7 +18983,8 @@ cmse_nonsecure_call_inline_register_clear (void)
call = SET_SRC (call);
/* Check if it is a cmse_nonsecure_call. */
- unspec = XEXP (call, 0);
+ unspec = XVECEXP (pat, 0, 2);
+
if (GET_CODE (unspec) != UNSPEC
|| XINT (unspec, 1) != UNSPEC_NONSECURE_MEM)
continue;
@@ -19010,7 +19011,7 @@ cmse_nonsecure_call_inline_register_clear (void)
/* Make sure the register used to hold the function address is not
cleared. */
- address = RTVEC_ELT (XVEC (unspec, 0), 0);
+ address = XEXP (call, 0);
gcc_assert (MEM_P (address));
gcc_assert (REG_P (XEXP (address, 0)));
address_regnum = REGNO (XEXP (address, 0));
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 5e5e112..537a3e2 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -8623,7 +8623,7 @@
if (detect_cmse_nonsecure_call (addr))
{
pat = gen_nonsecure_call_internal (operands[0], operands[1],
- operands[2]);
+ operands[2], const0_rtx);
emit_call_insn (pat);
}
else
@@ -8665,10 +8665,10 @@
(clobber (reg:SI LR_REGNUM))])])
(define_expand "nonsecure_call_internal"
- [(parallel [(call (unspec:SI [(match_operand 0 "memory_operand")]
- UNSPEC_NONSECURE_MEM)
+ [(parallel [(call (match_operand 0 "memory_operand")
(match_operand 1 "general_operand"))
(use (match_operand 2 "" ""))
+ (unspec:SI [(match_operand 3)] UNSPEC_NONSECURE_MEM)
(clobber (reg:SI LR_REGNUM))])]
"use_cmse"
{
@@ -8745,7 +8745,8 @@
if (detect_cmse_nonsecure_call (addr))
{
pat = gen_nonsecure_call_value_internal (operands[0], operands[1],
- operands[2], operands[3]);
+ operands[2], operands[3],
+ const0_rtx);
emit_call_insn (pat);
}
else
@@ -8779,10 +8780,10 @@
(define_expand "nonsecure_call_value_internal"
[(parallel [(set (match_operand 0 "" "")
- (call (unspec:SI [(match_operand 1 "memory_operand")]
- UNSPEC_NONSECURE_MEM)
+ (call (match_operand 1 "memory_operand")
(match_operand 2 "general_operand")))
(use (match_operand 3 "" ""))
+ (unspec:SI [(match_operand 4)] UNSPEC_NONSECURE_MEM)
(clobber (reg:SI LR_REGNUM))])]
"use_cmse"
"
diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
index f9e89e9..4da0086 100644
--- a/gcc/config/arm/thumb1.md
+++ b/gcc/config/arm/thumb1.md
@@ -1874,10 +1874,10 @@
)
(define_insn "*nonsecure_call_reg_thumb1_v5"
- [(call (unspec:SI [(mem:SI (reg:SI R4_REGNUM))]
- UNSPEC_NONSECURE_MEM)
+ [(call (mem:SI (reg:SI R4_REGNUM))
(match_operand 0 "" ""))
(use (match_operand 1 "" ""))
+ (unspec:SI [(match_operand 2)]UNSPEC_NONSECURE_MEM)
(clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB1 && use_cmse && !SIBLING_CALL_P (insn)"
"bl\\t__gnu_cmse_nonsecure_call"
@@ -1919,11 +1919,10 @@
(define_insn "*nonsecure_call_value_reg_thumb1_v5"
[(set (match_operand 0 "" "")
- (call (unspec:SI
- [(mem:SI (reg:SI R4_REGNUM))]
- UNSPEC_NONSECURE_MEM)
+ (call (mem:SI (reg:SI R4_REGNUM))
(match_operand 1 "" "")))
(use (match_operand 2 "" ""))
+ (unspec:SI [(match_operand 3)] UNSPEC_NONSECURE_MEM)
(clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB1 && use_cmse"
"bl\\t__gnu_cmse_nonsecure_call"
diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
index 019f9d4..2c2026b 100644
--- a/gcc/config/arm/thumb2.md
+++ b/gcc/config/arm/thumb2.md
@@ -537,10 +537,10 @@
)
(define_insn "*nonsecure_call_reg_thumb2_fpcxt"
- [(call (unspec:SI [(mem:SI (match_operand:SI 0 "s_register_operand" "l*r"))]
- UNSPEC_NONSECURE_MEM)
+ [(call (mem:SI (match_operand:SI 0 "s_register_operand" "l*r"))
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
+ (unspec:SI [(match_operand 3)] UNSPEC_NONSECURE_MEM)
(clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB2 && use_cmse && TARGET_HAVE_FPCXT_CMSE"
"blxns\\t%0"
@@ -549,10 +549,10 @@
)
(define_insn "*nonsecure_call_reg_thumb2"
- [(call (unspec:SI [(mem:SI (reg:SI R4_REGNUM))]
- UNSPEC_NONSECURE_MEM)
+ [(call (mem:SI (reg:SI R4_REGNUM))
(match_operand 0 "" ""))
(use (match_operand 1 "" ""))
+ (unspec:SI [(match_operand 2)] UNSPEC_NONSECURE_MEM)
(clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB2 && use_cmse && !TARGET_HAVE_FPCXT_CMSE"
"bl\\t__gnu_cmse_nonsecure_call"
@@ -573,11 +573,10 @@
(define_insn "*nonsecure_call_value_reg_thumb2_fpcxt"
[(set (match_operand 0 "" "")
- (call
- (unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "l*r"))]
- UNSPEC_NONSECURE_MEM)
- (match_operand 2 "" "")))
+ (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
+ (match_operand 2 "" "")))
(use (match_operand 3 "" ""))
+ (unspec:SI [(match_operand 4)] UNSPEC_NONSECURE_MEM)
(clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB2 && use_cmse && TARGET_HAVE_FPCXT_CMSE"
"blxns\\t%1"
@@ -587,10 +586,10 @@
(define_insn "*nonsecure_call_value_reg_thumb2"
[(set (match_operand 0 "" "")
- (call
- (unspec:SI [(mem:SI (reg:SI R4_REGNUM))] UNSPEC_NONSECURE_MEM)
- (match_operand 1 "" "")))
+ (call (mem:SI (reg:SI R4_REGNUM))
+ (match_operand 1 "" "")))
(use (match_operand 2 "" ""))
+ (unspec:SI [(match_operand 3)] UNSPEC_NONSECURE_MEM)
(clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB2 && use_cmse && !TARGET_HAVE_FPCXT_CMSE"
"bl\\t__gnu_cmse_nonsecure_call"
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 4d4e676..4c338c3 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -37,6 +37,8 @@ through the macros defined in the @file{.h} file.
* Trampolines:: Code set up at run time to enter a nested function.
* Library Calls:: Controlling how library routines are implicitly called.
* Addressing Modes:: Defining addressing modes valid for memory operands.
+* Vectorization:: Controlling how the vectorizer operates.
+* OpenMP and OpenACC:: Defining how OpenMP and OpenACC features should work.
* Anchored Addresses:: Defining how @option{-fsection-anchors} should work.
* Condition Code:: Defining how insns update the condition code.
* Costs:: Defining relative costs of different operations.
@@ -6282,6 +6284,10 @@ reciprocal of the machine-specific builtin function @var{fndecl}, or
@code{NULL_TREE} if such a function is not available.
@end deftypefn
+@node Vectorization
+@section Vectorization
+@cindex Vectorization
+
@deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD (void)
This hook should return the DECL of a function @var{f} that given an
address @var{addr} as an argument returns a mask @var{m} that can be
@@ -6522,6 +6528,10 @@ number of scalar elements in each scalar loop iteration that are to be
combined into the vector.
@end deftypefn
+@node OpenMP and OpenACC
+@section OpenMP and OpenACC
+@cindex OpenMP and OpenACC
+
@deftypefn {Target Hook} int TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN (struct cgraph_node *@var{}, struct cgraph_simd_clone *@var{}, @var{tree}, @var{int}, @var{bool})
This hook should set @var{vecsize_mangle}, @var{vecsize_int}, @var{vecsize_float}
fields in @var{simd_clone} structure pointed by @var{clone_info} argument and also
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 1a51ad5..12b8ed6 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -37,6 +37,8 @@ through the macros defined in the @file{.h} file.
* Trampolines:: Code set up at run time to enter a nested function.
* Library Calls:: Controlling how library routines are implicitly called.
* Addressing Modes:: Defining addressing modes valid for memory operands.
+* Vectorization:: Controlling how the vectorizer operates.
+* OpenMP and OpenACC:: Defining how OpenMP and OpenACC features should work.
* Anchored Addresses:: Defining how @option{-fsection-anchors} should work.
* Condition Code:: Defining how insns update the condition code.
* Costs:: Defining relative costs of different operations.
@@ -4273,6 +4275,10 @@ address; but often a machine-dependent strategy can generate better code.
@hook TARGET_BUILTIN_RECIPROCAL
+@node Vectorization
+@section Vectorization
+@cindex Vectorization
+
@hook TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD
@hook TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST
@@ -4313,6 +4319,10 @@ address; but often a machine-dependent strategy can generate better code.
@hook TARGET_VECTORIZE_PREFER_GATHER_SCATTER
+@node OpenMP and OpenACC
+@section OpenMP and OpenACC
+@cindex OpenMP and OpenACC
+
@hook TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN
@hook TARGET_SIMD_CLONE_ADJUST
diff --git a/gcc/testsuite/c-c++-common/asan/pr121389-1.c b/gcc/testsuite/c-c++-common/asan/pr121389-1.c
new file mode 100644
index 0000000..0116d7a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr121389-1.c
@@ -0,0 +1,23 @@
+// PR middle-end/121389
+// { dg-do compile { target musttail } }
+// { dg-options "-fsanitize=address" }
+
+int foo (void);
+int bar (void);
+int baz (unsigned *);
+
+int
+bar (void)
+{
+ do
+ {
+ unsigned t;
+ int u = baz (&t);
+ if (u == 42)
+ [[gnu::musttail]] return foo ();
+ if (u == -42)
+ break;
+ }
+ while (1);
+ return 42;
+}
diff --git a/gcc/testsuite/c-c++-common/asan/pr121389-2.c b/gcc/testsuite/c-c++-common/asan/pr121389-2.c
new file mode 100644
index 0000000..02914f8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr121389-2.c
@@ -0,0 +1,37 @@
+// PR middle-end/121389
+// { dg-do compile { target musttail } }
+// { dg-options "-fsanitize=address" }
+
+int foo (void);
+int bar (void);
+int baz (unsigned *);
+
+int
+bar (void)
+{
+ for (int a = 0; a < 420; ++a)
+ {
+ for (int b = 0; b < 420; ++b)
+ {
+ for (int c = 0; c < 420; ++c)
+ {
+ unsigned t;
+ int u = baz (&t);
+ if (u == 42)
+ [[gnu::musttail]] return foo ();
+ if (u == -42)
+ break;
+ if (u == 16)
+ goto l1;
+ if (u == 18)
+ goto l2;
+ if (u == 20)
+ goto l3;
+ }
+ l3:;
+ }
+ l2:;
+ }
+ l1:;
+ return 42;
+}
diff --git a/gcc/testsuite/c-c++-common/asan/pr121389-3.c b/gcc/testsuite/c-c++-common/asan/pr121389-3.c
new file mode 100644
index 0000000..5f71e06
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr121389-3.c
@@ -0,0 +1,130 @@
+// PR middle-end/121389
+// { dg-do compile { target musttail } }
+// { dg-options "-fsanitize=address" }
+
+int foo (void);
+int bar (void);
+int baz (unsigned *);
+
+int
+bar (void)
+{
+ for (int a = 0; a < 420; ++a)
+ {
+ for (int b = 0; b < 420; ++b)
+ {
+ for (int c = 0; c < 420; ++c)
+ {
+ unsigned t;
+ int u = baz (&t);
+ if (u == 42)
+ [[gnu::musttail]] return foo ();
+ if (u == -42)
+ break;
+ if (u == 16)
+ goto l1;
+ if (u == 18)
+ goto l2;
+ if (u == 20)
+ goto l3;
+ switch (u)
+ {
+ case 100: goto l100;
+ case 101: goto l101;
+ case 102: goto l102;
+ case 103: goto l103;
+ case 104: goto l104;
+ case 105: goto l105;
+ case 106: goto l106;
+ case 107: goto l107;
+ case 108: goto l108;
+ case 109: goto l109;
+ case 110: goto l110;
+ case 111: goto l111;
+ case 112: goto l112;
+ case 113: goto l113;
+ case 114: goto l114;
+ case 115: goto l115;
+ case 116: goto l116;
+ case 117: goto l117;
+ case 118: goto l118;
+ case 119: goto l119;
+ case 120: goto l120;
+ case 121: goto l121;
+ case 122: goto l122;
+ case 123: goto l123;
+ case 124: goto l124;
+ case 125: goto l125;
+ case 126: goto l126;
+ case 127: goto l127;
+ case 128: goto l128;
+ case 129: goto l129;
+ }
+ }
+ l3:;
+ foo ();
+ l100:
+ foo ();
+ l101:
+ foo ();
+ l102:
+ foo ();
+ l103:
+ foo ();
+ l104:
+ foo ();
+ l105:
+ foo ();
+ l106:
+ foo ();
+ l107:
+ foo ();
+ l108:
+ foo ();
+ l109:;
+ }
+ l2:;
+ foo ();
+ l110:
+ foo ();
+ l111:
+ foo ();
+ l112:
+ foo ();
+ l113:
+ foo ();
+ l114:
+ foo ();
+ l115:
+ foo ();
+ l116:
+ foo ();
+ l117:
+ foo ();
+ l118:
+ foo ();
+ l119:;
+ }
+ l1:;
+ foo ();
+ l120:
+ foo ();
+ l121:
+ foo ();
+ l122:
+ foo ();
+ l123:
+ foo ();
+ l124:
+ foo ();
+ l125:
+ foo ();
+ l126:
+ foo ();
+ l127:
+ foo ();
+ l128:
+ foo ();
+ l129:;
+ return 42;
+}
diff --git a/gcc/testsuite/c-c++-common/asan/pr121389-4.c b/gcc/testsuite/c-c++-common/asan/pr121389-4.c
new file mode 100644
index 0000000..2f7b410
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr121389-4.c
@@ -0,0 +1,6 @@
+// PR middle-end/121389
+// { dg-do compile { target musttail } }
+// { dg-options "-fsanitize=address -fdisable-tree-switchlower_O0" }
+// { dg-skip-if "" { *-*-* } { "*" } { "-O0" } }
+
+#include "pr121389-3.c"
diff --git a/gcc/testsuite/g++.target/aarch64/sve/pr121449.C b/gcc/testsuite/g++.target/aarch64/sve/pr121449.C
new file mode 100644
index 0000000..b2e1376
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/pr121449.C
@@ -0,0 +1,44 @@
+/* PR target/121449 */
+/* { dg-do assemble { target aarch64_asm_sve_ok } } */
+/* { dg-options "-O3 -save-temps" } */
+
+struct example;
+
+struct array {
+ unsigned length();
+ example *operator[](unsigned i) {
+ example **data = reinterpret_cast<example **>(this);
+ return data[i];
+ }
+};
+
+struct example {
+ int a[16];
+ bool is_even;
+ int version;
+ int count() { return is_even ? 2 : 1; }
+ void fun1(int, long);
+ void fun2(unsigned, unsigned);
+ void process(array &, array &);
+};
+
+bool found;
+
+void example::process(array &a, array &b) {
+ for (unsigned i = 1; a.length(); i++) {
+ long total = 0;
+ for (unsigned k = 0; k <= i; k++) {
+ total += a[k]->count();
+ }
+ for (unsigned j = 0; j < i; j++) {
+ int major = b[j]->version;
+ if (found)
+ major += i;
+ fun1(i + 1, total);
+ fun2(j, major);
+ }
+ }
+}
+
+/* { dg-final { scan-assembler-not {\tld1b\t(z[0-9]+)\.d, p[0-7]/z, \[(z[0-9]+)\.d, #64\]} } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/pr120986-1.c b/gcc/testsuite/gcc.target/aarch64/pr120986-1.c
new file mode 100644
index 0000000..e3bc56c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr120986-1.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=armv8.2-a+sve2+fp8dot2" } */
+#include <arm_sve.h>
+
+/* This triggered an ICE with an unrecognizable insn due to incorrect gating of
+ the insn in the backend. */
+svfloat16_t foo(svfloat16_t a, svmfloat8_t b, svmfloat8_t c, unsigned long fpm)
+{
+ return svdot_lane_fpm (a, b, c, 0, fpm);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/torture/pr120986-2.c b/gcc/testsuite/gcc.target/aarch64/torture/pr120986-2.c
new file mode 100644
index 0000000..1218dea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/torture/pr120986-2.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8.2-a+sve2+fp8dot2" } */
+#include <arm_sve.h>
+svfloat16_t foo(svfloat16_t a, svmfloat8_t b, svmfloat8_t c)
+{
+ return svdot_lane_fpm (a, b, c, 0, 0);
+}
diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-18.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-18.c
index db7d975..eb8a358 100644
--- a/gcc/testsuite/gcc.target/arm/cmse/cmse-18.c
+++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-18.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-mcmse -fdump-rtl-final-slim" } */
+/* Make sure FPCXT is not enabled. */
+/* { dg-options "-mcmse -fdump-rtl-final -march=armv8-m.main+fp" } */
typedef void (*f)(int) __attribute__((cmse_nonsecure_call));
@@ -8,5 +9,5 @@ void bar(f func, int a)
func(a);
}
-/* { dg-final { scan-rtl-dump "call unspec\\\[\\\[r4:SI\\\]\\\]" "final" { target { ! arm_v8_1m_mve_ok } } } } */
-/* { dg-final { scan-rtl-dump "call unspec\\\[\\\[r\[0-7\]:SI\\\]\\\]" "final" { target { arm_v8_1m_mve_ok } } } } */
+/* { dg-final { scan-rtl-dump "call \\\(mem:SI \\\(reg:SI 4 r4" "final" } } */
+/* { dg-final { scan-rtl-dump "UNSPEC_NONSECURE_MEM" "final" } } */
diff --git a/gcc/testsuite/gcc.target/arm/cmse/cmse-19.c b/gcc/testsuite/gcc.target/arm/cmse/cmse-19.c
new file mode 100644
index 0000000..ae075c3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/cmse/cmse-19.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* This is a duplicate of cmse-18.c, targetting arm_v8_1m_mve, to make sure
+ FPCXT is enabled. */
+/* { dg-options "-mcmse -fdump-rtl-final -march=armv8.1-m.main+mve" } */
+
+typedef void (*f)(int) __attribute__((cmse_nonsecure_call));
+
+void bar(f func, int a)
+{
+ func(a);
+}
+
+/* { dg-final { scan-rtl-dump "call \\\(mem:SI \\\(reg/f:SI \[0-7] r\[0-7\]" "final" } } */
+/* { dg-final { scan-rtl-dump "UNSPEC_NONSECURE_MEM" "final" } } */
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index 1c113f8..ccd8080 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -5643,15 +5643,24 @@ visit_nary_op (tree lhs, gassign *stmt)
&& vn_get_stmt_kind (ass) == VN_REFERENCE)
{
tree last_vuse = gimple_vuse (ass);
- tree op = build3 (BIT_FIELD_REF, TREE_TYPE (rhs1),
- gimple_assign_rhs1 (ass),
- TREE_OPERAND (rhs1, 1), TREE_OPERAND (rhs1, 2));
- tree result = vn_reference_lookup (op, gimple_vuse (ass),
- default_vn_walk_kind,
- NULL, true, &last_vuse);
- if (result
- && useless_type_conversion_p (type, TREE_TYPE (result)))
- return set_ssa_val_to (lhs, result);
+ tree op = gimple_assign_rhs1 (ass);
+ /* Avoid building invalid and unexpected refs. */
+ if (TREE_CODE (op) != TARGET_MEM_REF
+ && TREE_CODE (op) != BIT_FIELD_REF
+ && TREE_CODE (op) != REALPART_EXPR
+ && TREE_CODE (op) != IMAGPART_EXPR)
+ {
+ tree op = build3 (BIT_FIELD_REF, TREE_TYPE (rhs1),
+ gimple_assign_rhs1 (ass),
+ TREE_OPERAND (rhs1, 1),
+ TREE_OPERAND (rhs1, 2));
+ tree result = vn_reference_lookup (op, gimple_vuse (ass),
+ default_vn_walk_kind,
+ NULL, true, &last_vuse);
+ if (result
+ && useless_type_conversion_p (type, TREE_TYPE (result)))
+ return set_ssa_val_to (lhs, result);
+ }
}
}
break;
diff --git a/gcc/tree-tailcall.cc b/gcc/tree-tailcall.cc
index c80145d..d04394f 100644
--- a/gcc/tree-tailcall.cc
+++ b/gcc/tree-tailcall.cc
@@ -605,6 +605,12 @@ find_tail_calls (basic_block bb, edge esucc, struct tailcall **ret,
&& (stmt = last_nondebug_stmt (bb))
&& gimple_code (stmt) == GIMPLE_COND)
;
+ else if (esucc
+ && cfun->has_musttail
+ && diag_musttail
+ && (stmt = last_nondebug_stmt (bb))
+ && gimple_code (stmt) == GIMPLE_SWITCH)
+ ;
/* If there is an abnormal edge assume it's the only extra one.
Tolerate that case so that we can give better error messages
for musttail later. */
@@ -668,7 +674,7 @@ find_tail_calls (basic_block bb, edge esucc, struct tailcall **ret,
else
goto <bb 6>; [INV]
When walking backwards, ESUCC is the edge we are coming from,
- depending on its EDGE_TRUE_FLAG, == vs. != for the comparison
+ depending on its EDGE_TRUE_FLAG, comparison code
and value compared against try to find out through which edge
we need to go and which edge should be ignored. The code handles
both INTEGER_CST PHI arguments and SSA_NAMEs set to constants
@@ -677,19 +683,16 @@ find_tail_calls (basic_block bb, edge esucc, struct tailcall **ret,
&& diag_musttail
&& esucc
&& gimple_code (stmt) == GIMPLE_COND
- && (gimple_cond_code (stmt) == EQ_EXPR
- || gimple_cond_code (stmt) == NE_EXPR)
&& TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME
&& TREE_CODE (gimple_cond_rhs (stmt)) == INTEGER_CST
&& INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
- && (integer_zerop (gimple_cond_rhs (stmt))
- || integer_onep (gimple_cond_rhs (stmt))))
+ && tree_int_cst_sgn (gimple_cond_rhs (stmt)) >= 0)
{
tree lhs = gimple_cond_lhs (stmt);
- bool rhsv = integer_onep (gimple_cond_rhs (stmt));
- if (((esucc->flags & EDGE_TRUE_VALUE) != 0)
- ^ (gimple_cond_code (stmt) == EQ_EXPR))
- rhsv = !rhsv;
+ tree_code ccode = gimple_cond_code (stmt);
+ tree rhsv = gimple_cond_rhs (stmt);
+ if ((esucc->flags & EDGE_FALSE_VALUE) != 0)
+ ccode = invert_tree_comparison (ccode, false);
if (!ignored_edges)
{
ignored_edges = new hash_set<edge>;
@@ -700,8 +703,10 @@ find_tail_calls (basic_block bb, edge esucc, struct tailcall **ret,
&& (gimple_assign_rhs_code (SSA_NAME_DEF_STMT (lhs))
== INTEGER_CST))
{
- tree rhs = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (lhs));
- if (rhsv ? integer_onep (rhs) : integer_zerop (rhs))
+ tree lhsv = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (lhs));
+
+ if (const_binop (ccode, boolean_type_node, lhsv, rhsv)
+ == boolean_true_node)
continue;
}
else if (gimple_code (SSA_NAME_DEF_STMT (lhs)) == GIMPLE_PHI)
@@ -712,15 +717,62 @@ find_tail_calls (basic_block bb, edge esucc, struct tailcall **ret,
edge_iterator ei;
FOR_EACH_EDGE (e, ei, pbb->preds)
{
- tree rhs = gimple_phi_arg_def_from_edge (phi, e);
- if (TREE_CODE (rhs) == SSA_NAME
- && is_gimple_assign (SSA_NAME_DEF_STMT (rhs))
- && (gimple_assign_rhs_code (SSA_NAME_DEF_STMT (rhs))
+ tree lhsv = gimple_phi_arg_def_from_edge (phi, e);
+ if (TREE_CODE (lhsv) == SSA_NAME
+ && is_gimple_assign (SSA_NAME_DEF_STMT (lhsv))
+ && (gimple_assign_rhs_code (SSA_NAME_DEF_STMT (lhsv))
== INTEGER_CST))
- rhs = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (rhs));
- if (!(rhsv ? integer_onep (rhs) : integer_zerop (rhs)))
+ lhsv = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (lhsv));
+ if (TREE_CODE (lhsv) != INTEGER_CST
+ || const_binop (ccode, boolean_type_node,
+ lhsv, rhsv) != boolean_true_node)
ignored_edges->add (e);
}
+ continue;
+ }
+ }
+ if (cfun->has_musttail
+ && diag_musttail
+ && esucc
+ && gimple_code (stmt) == GIMPLE_SWITCH
+ && (TREE_CODE (gimple_switch_index (as_a <gswitch *> (stmt)))
+ == SSA_NAME))
+ {
+ gswitch *swtch = as_a <gswitch *> (stmt);
+ tree idx = gimple_switch_index (swtch);
+ if (!ignored_edges)
+ {
+ ignored_edges = new hash_set<edge>;
+ must_see_bbs = new hash_set<basic_block>;
+ delete_ignored_edges = true;
+ }
+ if (is_gimple_assign (SSA_NAME_DEF_STMT (idx))
+ && (gimple_assign_rhs_code (SSA_NAME_DEF_STMT (idx))
+ == INTEGER_CST))
+ {
+ tree val = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (idx));
+ if (find_taken_edge_switch_expr (swtch, val) == esucc)
+ continue;
+ }
+ else if (gimple_code (SSA_NAME_DEF_STMT (idx)) == GIMPLE_PHI)
+ {
+ gimple *phi = SSA_NAME_DEF_STMT (idx);
+ basic_block pbb = gimple_bb (phi);
+ must_see_bbs->add (pbb);
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, pbb->preds)
+ {
+ tree val = gimple_phi_arg_def_from_edge (phi, e);
+ if (TREE_CODE (val) == SSA_NAME
+ && is_gimple_assign (SSA_NAME_DEF_STMT (val))
+ && (gimple_assign_rhs_code (SSA_NAME_DEF_STMT (val))
+ == INTEGER_CST))
+ val = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (val));
+ if (TREE_CODE (val) != INTEGER_CST
+ || find_taken_edge_switch_expr (swtch, val) != esucc)
+ ignored_edges->add (e);
+ }
+ continue;
}
}
@@ -1138,47 +1190,67 @@ find_tail_calls (basic_block bb, edge esucc, struct tailcall **ret,
if (ignored_edges)
{
if (is_gimple_assign (stmt)
- && gimple_assign_rhs_code (stmt) == INTEGER_CST)
+ && gimple_assign_rhs_code (stmt) == INTEGER_CST
+ && tree_int_cst_sgn (gimple_assign_rhs1 (stmt)) >= 0)
{
use_operand_p use_p;
- gimple *use_stmt;
- if ((integer_zerop (gimple_assign_rhs1 (stmt))
- || integer_onep (gimple_assign_rhs1 (stmt)))
- && single_imm_use (gimple_assign_lhs (stmt), &use_p,
- &use_stmt))
+ imm_use_iterator imm_iter;
+ bool bad_p = false;
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter,
+ gimple_assign_lhs (stmt))
{
- if (gimple_code (use_stmt) == GIMPLE_COND)
- continue;
- if (gimple_code (use_stmt) == GIMPLE_PHI
- && single_imm_use (gimple_phi_result (use_stmt),
- &use_p, &use_stmt)
- && gimple_code (use_stmt) == GIMPLE_COND)
+ gimple *use_stmt = USE_STMT (use_p);
+ if (is_gimple_debug (use_stmt)
+ || gimple_code (use_stmt) == GIMPLE_COND
+ || gimple_code (use_stmt) == GIMPLE_SWITCH)
continue;
+ if (gimple_code (use_stmt) == GIMPLE_PHI)
+ {
+ use_operand_p use_p2;
+ imm_use_iterator imm_iter2;
+ FOR_EACH_IMM_USE_FAST (use_p2, imm_iter2,
+ gimple_phi_result (use_stmt))
+ {
+ gimple *use_stmt2 = USE_STMT (use_p2);
+ if (is_gimple_debug (use_stmt2)
+ || gimple_code (use_stmt2) == GIMPLE_COND
+ || gimple_code (use_stmt2) == GIMPLE_SWITCH)
+ continue;
+ bad_p = true;
+ break;
+ }
+ if (bad_p)
+ break;
+ }
+ else
+ {
+ bad_p = true;
+ break;
+ }
}
+ if (!bad_p)
+ continue;
}
if (gimple_code (stmt) == GIMPLE_COND
- && (gimple_cond_code (stmt) == EQ_EXPR
- || gimple_cond_code (stmt) == NE_EXPR)
&& TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME
&& TREE_CODE (gimple_cond_rhs (stmt)) == INTEGER_CST
&& INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
- && (integer_zerop (gimple_cond_rhs (stmt))
- || integer_onep (gimple_cond_rhs (stmt))))
+ && tree_int_cst_sgn (gimple_cond_rhs (stmt)) >= 0)
{
edge e = NULL, et, ef;
+ enum tree_code ccode = gimple_cond_code (stmt);
tree lhs = gimple_cond_lhs (stmt);
- bool rhsv = integer_onep (gimple_cond_rhs (stmt));
- if (gimple_cond_code (stmt) == NE_EXPR)
- rhsv = !rhsv;
+ tree rhsv = gimple_cond_rhs (stmt);
extract_true_false_edges_from_block (gimple_bb (stmt), &et, &ef);
if (is_gimple_assign (SSA_NAME_DEF_STMT (lhs))
&& (gimple_assign_rhs_code (SSA_NAME_DEF_STMT (lhs))
== INTEGER_CST))
{
- tree rhs = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (lhs));
- if (rhsv ? integer_onep (rhs) : integer_zerop (rhs))
+ tree lhsv = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (lhs));
+ tree r = const_binop (ccode, boolean_type_node, lhsv, rhsv);
+ if (r == boolean_true_node)
e = et;
- else if (rhsv ? integer_zerop (rhs) : integer_onep (rhs))
+ else if (r == boolean_false_node)
e = ef;
}
else if (gimple_code (SSA_NAME_DEF_STMT (lhs)) == GIMPLE_PHI)
@@ -1188,16 +1260,17 @@ find_tail_calls (basic_block bb, edge esucc, struct tailcall **ret,
for (edge e2 : edges)
if (e2->dest == pbb)
{
- tree rhs = gimple_phi_arg_def_from_edge (phi, e2);
- if (TREE_CODE (rhs) == SSA_NAME)
- if (gimple *g = SSA_NAME_DEF_STMT (rhs))
+ tree lhsv = gimple_phi_arg_def_from_edge (phi, e2);
+ if (TREE_CODE (lhsv) == SSA_NAME)
+ if (gimple *g = SSA_NAME_DEF_STMT (lhsv))
if (is_gimple_assign (g)
&& gimple_assign_rhs_code (g) == INTEGER_CST)
- rhs = gimple_assign_rhs1 (g);
- if (rhsv ? integer_onep (rhs) : integer_zerop (rhs))
+ lhsv = gimple_assign_rhs1 (g);
+ tree r = const_binop (ccode, boolean_type_node,
+ lhsv, rhsv);
+ if (r == boolean_true_node)
e = et;
- else if (rhsv ? integer_zerop (rhs)
- : integer_onep (rhs))
+ else if (r == boolean_false_node)
e = ef;
break;
}
@@ -1212,6 +1285,48 @@ find_tail_calls (basic_block bb, edge esucc, struct tailcall **ret,
goto new_bb;
}
}
+ if (gimple_code (stmt) == GIMPLE_SWITCH
+ && (TREE_CODE (gimple_switch_index (as_a <gswitch *> (stmt)))
+ == SSA_NAME))
+ {
+ edge e = NULL;
+ gswitch *swtch = as_a <gswitch *> (stmt);
+ tree idx = gimple_switch_index (swtch);
+ if (is_gimple_assign (SSA_NAME_DEF_STMT (idx))
+ && (gimple_assign_rhs_code (SSA_NAME_DEF_STMT (idx))
+ == INTEGER_CST))
+ {
+ tree val = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (idx));
+ e = find_taken_edge_switch_expr (swtch, val);
+ }
+ else if (gimple_code (SSA_NAME_DEF_STMT (idx)) == GIMPLE_PHI)
+ {
+ gimple *phi = SSA_NAME_DEF_STMT (idx);
+ basic_block pbb = gimple_bb (phi);
+ for (edge e2 : edges)
+ if (e2->dest == pbb)
+ {
+ tree val = gimple_phi_arg_def_from_edge (phi, e2);
+ if (TREE_CODE (val) == SSA_NAME)
+ if (gimple *g = SSA_NAME_DEF_STMT (val))
+ if (is_gimple_assign (g)
+ && gimple_assign_rhs_code (g) == INTEGER_CST)
+ val = gimple_assign_rhs1 (g);
+ if (TREE_CODE (val) == INTEGER_CST)
+ e = find_taken_edge_switch_expr (swtch, val);
+ break;
+ }
+ }
+ if (e)
+ {
+ ass_var = propagate_through_phis (ass_var, e);
+ if (!ass_var || ignored_edges)
+ edges.safe_push (e);
+ abb = e->dest;
+ agsi = gsi_start_bb (abb);
+ goto new_bb;
+ }
+ }
}
if (gimple_code (stmt) != GIMPLE_ASSIGN)
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index cab503c..5fc24dc 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -163,169 +163,6 @@ static void vect_estimate_min_profitable_iters (loop_vec_info, int *, int *,
static stmt_vec_info vect_is_simple_reduction (loop_vec_info, stmt_vec_info,
bool *, bool *, bool);
-/* Subroutine of vect_determine_vf_for_stmt that handles only one
- statement. VECTYPE_MAYBE_SET_P is true if STMT_VINFO_VECTYPE
- may already be set for general statements (not just data refs). */
-
-static opt_result
-vect_determine_vectype_for_stmt_1 (vec_info *vinfo, stmt_vec_info stmt_info,
- bool vectype_maybe_set_p)
-{
- gimple *stmt = stmt_info->stmt;
-
- if ((!STMT_VINFO_RELEVANT_P (stmt_info)
- && !STMT_VINFO_LIVE_P (stmt_info))
- || gimple_clobber_p (stmt))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location, "skip.\n");
- return opt_result::success ();
- }
-
- tree stmt_vectype, nunits_vectype;
- opt_result res = vect_get_vector_types_for_stmt (vinfo, stmt_info,
- &stmt_vectype,
- &nunits_vectype);
- if (!res)
- return res;
-
- if (stmt_vectype)
- {
- if (STMT_VINFO_VECTYPE (stmt_info))
- /* The only case when a vectype had been already set is for stmts
- that contain a data ref, or for "pattern-stmts" (stmts generated
- by the vectorizer to represent/replace a certain idiom). */
- gcc_assert ((STMT_VINFO_DATA_REF (stmt_info)
- || vectype_maybe_set_p)
- && STMT_VINFO_VECTYPE (stmt_info) == stmt_vectype);
- else
- STMT_VINFO_VECTYPE (stmt_info) = stmt_vectype;
- }
-
- return opt_result::success ();
-}
-
-/* Subroutine of vect_determine_vectorization_factor. Set the vector
- types of STMT_INFO and all attached pattern statements and update
- the vectorization factor VF accordingly. Return true on success
- or false if something prevented vectorization. */
-
-static opt_result
-vect_determine_vectype_for_stmt (vec_info *vinfo, stmt_vec_info stmt_info)
-{
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: %G",
- stmt_info->stmt);
- opt_result res = vect_determine_vectype_for_stmt_1 (vinfo, stmt_info, false);
- if (!res)
- return res;
-
- if (STMT_VINFO_IN_PATTERN_P (stmt_info)
- && STMT_VINFO_RELATED_STMT (stmt_info))
- {
- gimple *pattern_def_seq = STMT_VINFO_PATTERN_DEF_SEQ (stmt_info);
- stmt_info = STMT_VINFO_RELATED_STMT (stmt_info);
-
- /* If a pattern statement has def stmts, analyze them too. */
- for (gimple_stmt_iterator si = gsi_start (pattern_def_seq);
- !gsi_end_p (si); gsi_next (&si))
- {
- stmt_vec_info def_stmt_info = vinfo->lookup_stmt (gsi_stmt (si));
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "==> examining pattern def stmt: %G",
- def_stmt_info->stmt);
- res = vect_determine_vectype_for_stmt_1 (vinfo, def_stmt_info, true);
- if (!res)
- return res;
- }
-
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "==> examining pattern statement: %G",
- stmt_info->stmt);
- res = vect_determine_vectype_for_stmt_1 (vinfo, stmt_info, true);
- if (!res)
- return res;
- }
-
- return opt_result::success ();
-}
-
-/* Function vect_set_stmts_vectype
-
- Set STMT_VINFO_VECTYPE of all stmts. */
-
-static opt_result
-vect_set_stmts_vectype (loop_vec_info loop_vinfo)
-{
- class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
- basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
- unsigned nbbs = loop->num_nodes;
- tree scalar_type = NULL_TREE;
- gphi *phi;
- tree vectype;
- stmt_vec_info stmt_info;
- unsigned i;
-
- DUMP_VECT_SCOPE ("vect_set_stmts_vectype");
-
- for (i = 0; i < nbbs; i++)
- {
- basic_block bb = bbs[i];
-
- for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si);
- gsi_next (&si))
- {
- phi = si.phi ();
- stmt_info = loop_vinfo->lookup_stmt (phi);
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location, "==> examining phi: %G",
- (gimple *) phi);
-
- gcc_assert (stmt_info);
-
- if (STMT_VINFO_RELEVANT_P (stmt_info)
- || STMT_VINFO_LIVE_P (stmt_info))
- {
- gcc_assert (!STMT_VINFO_VECTYPE (stmt_info));
- scalar_type = TREE_TYPE (PHI_RESULT (phi));
-
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "get vectype for scalar type: %T\n",
- scalar_type);
-
- vectype = get_vectype_for_scalar_type (loop_vinfo, scalar_type);
- if (!vectype)
- return opt_result::failure_at (phi,
- "not vectorized: unsupported "
- "data-type %T\n",
- scalar_type);
- STMT_VINFO_VECTYPE (stmt_info) = vectype;
-
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location, "vectype: %T\n",
- vectype);
- }
- }
-
- for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
- gsi_next (&si))
- {
- if (is_gimple_debug (gsi_stmt (si)))
- continue;
- stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
- opt_result res
- = vect_determine_vectype_for_stmt (loop_vinfo, stmt_info);
- if (!res)
- return res;
- }
- }
-
- return opt_result::success ();
-}
-
/* Function vect_is_simple_iv_evolution.
@@ -2483,15 +2320,6 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo, bool &fatal,
}
LOOP_VINFO_MAX_VECT_FACTOR (loop_vinfo) = max_vf;
- ok = vect_set_stmts_vectype (loop_vinfo);
- if (!ok)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "cannot determine vector types.\n");
- return ok;
- }
-
/* Compute the scalar iteration cost. */
vect_compute_single_scalar_iteration_cost (loop_vinfo);
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index eff5e88..26d5be5 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -724,14 +724,21 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo, bool *fatal)
if (vect_stmt_relevant_p (phi_info, loop_vinfo, &relevant, &live_p))
vect_mark_relevant (&worklist, phi_info, relevant, live_p);
}
- for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+ for (si = gsi_after_labels (bb); !gsi_end_p (si); gsi_next (&si))
{
- if (is_gimple_debug (gsi_stmt (si)))
+ gimple *stmt = gsi_stmt (si);
+ if (is_gimple_debug (stmt))
continue;
- stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
+ stmt_vec_info stmt_info = loop_vinfo->lookup_stmt (stmt);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
- "init: stmt relevant? %G", stmt_info->stmt);
+ "init: stmt relevant? %G", stmt);
+
+ if (gimple_get_lhs (stmt) == NULL_TREE
+ && !is_a <gcond *> (stmt)
+ && !is_a <gcall *> (stmt))
+ return opt_result::failure_at
+ (stmt, "not vectorized: irregular stmt: %G", stmt);
if (vect_stmt_relevant_p (stmt_info, loop_vinfo, &relevant, &live_p))
vect_mark_relevant (&worklist, stmt_info, relevant, live_p);