This enables early-exit vectorization on s390x.
Adjust the test suite since s390x does not support variable length
vectors and only supports basic vector load schemes.
gcc/ChangeLog:
* config/s390/s390-protos.h (s390_expand_vec_compare_gen_cc):
New function.
* config/s390/s390.cc (s390_expand_vec_compare_cc): Extract
part of this function into a ...
(s390_expand_vec_compare_gen_cc): ... new function.
* config/s390/vector.md (vec_cbranch_any<mode>): Implement.
(vec_cbranch_all<mode>): Implement.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/gen-vect-11.c: Adjust.
* gcc.dg/tree-ssa/gen-vect-11a.c: Adjust.
* gcc.dg/vect/vect-early-break_52.c: Adjust.
* gcc.dg/vect/vect-early-break_53.c: Adjust.
* gcc.dg/vect/vect-early-break_64.c: Adjust.
* gcc.dg/vect/vect-uncounted_2.c: Adjust.
* lib/target-supports.exp: Add s390x to early-break
vectorization
Signed-off-by: Juergen Christ <[email protected]>
---
gcc/config/s390/s390-protos.h | 1 +
gcc/config/s390/s390.cc | 40 ++++++++-----
gcc/config/s390/vector.md | 60 +++++++++++++++++++
gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11.c | 7 +--
gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11a.c | 4 +-
.../gcc.dg/vect/vect-early-break_52.c | 2 +-
.../gcc.dg/vect/vect-early-break_53.c | 2 +-
.../gcc.dg/vect/vect-early-break_64.c | 2 +-
gcc/testsuite/gcc.dg/vect/vect-uncounted_2.c | 2 +-
gcc/testsuite/lib/target-supports.exp | 4 ++
10 files changed, 100 insertions(+), 24 deletions(-)
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index bedce5830720..e885ad1beb19 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -122,6 +122,7 @@ extern void s390_expand_atomic (machine_mode, enum rtx_code,
rtx, rtx, rtx, bool);
extern void s390_expand_tbegin (rtx, rtx, rtx, bool);
extern void s390_expand_vec_compare (rtx, enum rtx_code, rtx, rtx);
+extern rtx s390_expand_vec_compare_gen_cc (enum rtx_code, rtx, rtx, bool);
extern void s390_expand_vec_compare_cc (rtx, enum rtx_code, rtx, rtx, bool);
extern enum rtx_code s390_reverse_condition (machine_mode, enum rtx_code);
extern void s390_expand_vcond (rtx, rtx, rtx, enum rtx_code, rtx, rtx);
diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index 1bddd5e454ae..89161674e44a 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -7449,18 +7449,14 @@ s390_expand_vec_compare (rtx target, enum rtx_code cond,
emit_insn (gen_rtx_SET (target, gen_rtx_NOT (mode, target)));
}
-/* Expand the comparison CODE of CMP1 and CMP2 and copy 1 or 0 into
- TARGET if either all (ALL_P is true) or any (ALL_P is false) of the
- elements in CMP1 and CMP2 fulfill the comparison.
- This function is only used in s390_expand_cstoreti4 and to emit patterns for
- the vx builtins and therefore only handles comparison codes required by
- those. */
-void
-s390_expand_vec_compare_cc (rtx target, enum rtx_code code,
- rtx cmp1, rtx cmp2, bool all_p)
+/* Expand the comparison CODE of CMP1 and CMP2 and return a comparison suitable
+ for s390_emit_jump which jumps if all (ALLP is true) or any (ALL_P is false)
+ of the elements in CMP1 and CMP2 fulfill the comparison. */
+rtx
+s390_expand_vec_compare_gen_cc (enum rtx_code code,
+ rtx cmp1, rtx cmp2, bool all_p)
{
machine_mode cc_producer_mode, cc_consumer_mode, scratch_mode;
- rtx tmp_reg = gen_reg_rtx (SImode);
bool swap_p = false;
if (GET_MODE_CLASS (GET_MODE (cmp1)) == MODE_VECTOR_INT
@@ -7543,14 +7539,30 @@ s390_expand_vec_compare_cc (rtx target, enum rtx_code
code,
gen_rtx_COMPARE (cc_producer_mode, cmp1, cmp2)),
gen_rtx_CLOBBER (VOIDmode,
gen_rtx_SCRATCH (scratch_mode)))));
+
+ return gen_rtx_fmt_ee (code, VOIDmode,
+ gen_rtx_REG (cc_consumer_mode, CC_REGNUM),
+ const0_rtx);
+}
+
+/* Expand the comparison CODE of CMP1 and CMP2 and copy 1 or 0 into
+ TARGET if either all (ALL_P is true) or any (ALL_P is false) of the
+ elements in CMP1 and CMP2 fulfill the comparison.
+ This function is only used in s390_expand_cstoreti4 and to emit patterns for
+ the vx builtins and therefore only handles comparison codes required by
+ those. */
+void
+s390_expand_vec_compare_cc (rtx target, enum rtx_code code,
+ rtx cmp1, rtx cmp2, bool all_p)
+{
+ rtx cond = s390_expand_vec_compare_gen_cc (code, cmp1, cmp2, all_p);
+ rtx tmp_reg = gen_reg_rtx (SImode);
+
emit_move_insn (target, const0_rtx);
emit_move_insn (tmp_reg, const1_rtx);
emit_move_insn (target,
- gen_rtx_IF_THEN_ELSE (SImode,
- gen_rtx_fmt_ee (code, VOIDmode,
- gen_rtx_REG (cc_consumer_mode, CC_REGNUM),
- const0_rtx),
+ gen_rtx_IF_THEN_ELSE (SImode, cond,
tmp_reg, target));
}
diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md
index f0be6f10c1ac..b806f4c3300d 100644
--- a/gcc/config/s390/vector.md
+++ b/gcc/config/s390/vector.md
@@ -3967,3 +3967,63 @@
operands[8] = gen_reg_rtx (V16QImode);
operands[9] = gen_reg_rtx (V16QImode);
})
+
+(define_expand "vec_cbranch_any<mode>"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:VIT_HW_VXE3_T 1 "register_operand" "")
+ (match_operand:VIT_HW_VXE3_T 2 "register_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_VX"
+{
+ s390_emit_jump (operands[3],
+ s390_expand_vec_compare_gen_cc (GET_CODE (operands[0]),
+ operands[1], operands[2], false));
+ DONE;
+})
+
+(define_expand "vec_cbranch_all<mode>"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:VIT_HW_VXE3_T 1 "register_operand" "")
+ (match_operand:VIT_HW_VXE3_T 2 "register_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_VX"
+{
+ s390_emit_jump (operands[3],
+ s390_expand_vec_compare_gen_cc (GET_CODE (operands[0]),
+ operands[1], operands[2], true));
+ DONE;
+})
+
+(define_expand "vec_cbranch_any<mode>"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:VECF_HW 1 "register_operand" "")
+ (match_operand:VECF_HW 2 "register_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_VX"
+{
+ s390_emit_jump (operands[3],
+ s390_expand_vec_compare_gen_cc (GET_CODE (operands[0]),
+ operands[1], operands[2], false));
+ DONE;
+})
+
+(define_expand "vec_cbranch_all<mode>"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:VECF_HW 1 "register_operand" "")
+ (match_operand:VECF_HW 2 "register_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ "TARGET_VX"
+{
+ s390_emit_jump (operands[3],
+ s390_expand_vec_compare_gen_cc (GET_CODE (operands[0]),
+ operands[1], operands[2], true));
+ DONE;
+})
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11.c
b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11.c
index 6916843f397b..9b5098b50992 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11.c
@@ -1,10 +1,6 @@
/* { dg-do run { target vect_cmdline_needed } } */
/* { dg-options "-O2 -ftree-vectorize -fwrapv -fdump-tree-vect-details
-fvect-cost-model=dynamic" } */
/* { dg-additional-options "-mno-sse" { target { i?86-*-* x86_64-*-* } } } */
-/* The IBM Z backend sets the min-vect-loop-bound param to 2 to avoid
- awkward epilogue code generation in some cases. This line needs to
- be removed after finding an alternate way to fix this. */
-/* { dg-additional-options "--param min-vect-loop-bound=0" { target {
s390*-*-* } } } */
#include <stdlib.h>
@@ -34,4 +30,5 @@ int main ()
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target {
! { avr-*-* msp430-*-* pru-*-* } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target {
! { avr-*-* msp430-*-* pru-*-* s390*-*-* } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target {
s390*-*-* } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11a.c
b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11a.c
index 6326bf75ab02..721a609acffb 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11a.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11a.c
@@ -38,4 +38,6 @@ int main ()
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target {
! { avr-*-* pru-*-* } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target {
! { avr-*-* msp430-*-* pru-*-* s390*-*-* } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target {
s390*-*-* } } } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_52.c
b/gcc/testsuite/gcc.dg/vect/vect-early-break_52.c
index 6abfcd6580e4..f7e6a6c2eb93 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-early-break_52.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_52.c
@@ -18,4 +18,4 @@ int main1 (short X)
}
}
-/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" {
target { ! "x86_64-*-* i?86-*-* arm*-*-*" } } } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" {
target { ! "x86_64-*-* i?86-*-* arm*-*-* s390*-*-*" } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_53.c
b/gcc/testsuite/gcc.dg/vect/vect-early-break_53.c
index d4fd0d39a25a..876baa980272 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-early-break_53.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_53.c
@@ -16,4 +16,4 @@ int main ()
abort ();
}
-/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" {
target { ! s390*-*-* } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_64.c
b/gcc/testsuite/gcc.dg/vect/vect-early-break_64.c
index aaa2a46fb67e..52d7ebdd1797 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-early-break_64.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_64.c
@@ -15,4 +15,4 @@ void a() {
return;
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target
vect_partial_vectors } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target {
vect_partial_vectors && { ! s390*-*-* } } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-uncounted_2.c
b/gcc/testsuite/gcc.dg/vect/vect-uncounted_2.c
index 33fb0ce1f0d0..390bf22ee1fa 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-uncounted_2.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-uncounted_2.c
@@ -13,7 +13,7 @@ foo (int *a0, int *aN, int *b0, int *bN)
*a += *b;
}
-/* { dg-final { scan-tree-dump "Loop being analyzed as uncounted." "vect" } }
*/
+/* { dg-final { scan-tree-dump "Loop being analyzed as uncounted." "vect" {
target { ! "s390*-*-*" } } } } */
/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
/* Make sure the values used in peeled epilog loop effectively reset the last
vectorized iteration. */
/* { dg-final { scan-tree-dump {<bb ([0-9]+)>[^\n\r]*:.+# (a_[0-9]+) = PHI
<a_[0-9]+\([0-9]+\).+<bb [0-9]+>[^\n\r]*:.+# a_[0-9]+ = PHI <\2\(\1\)>} "vect"
} } */
diff --git a/gcc/testsuite/lib/target-supports.exp
b/gcc/testsuite/lib/target-supports.exp
index c6ebbed4f4b5..e76b2b77c4c0 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -4713,6 +4713,8 @@ proc check_effective_target_vect_early_break { } {
|| [istarget amdgcn-*-*]
|| [check_effective_target_riscv_v]
|| [check_effective_target_loongarch_sx]
+ || ([istarget s390*-*-*]
+ && [check_effective_target_s390_vx])
}}]
}
@@ -4730,6 +4732,8 @@ proc check_effective_target_vect_early_break_hw { } {
|| [istarget amdgcn-*-*]
|| [check_effective_target_riscv_v_ok]
|| [check_effective_target_loongarch_sx_hw]
+ || ([istarget s390*-*-*]
+ && [check_effective_target_s390_vx])
}}]
}
--
2.43.7