[gcc r17-2608] s390x: Implement vec_cbranch_{all,any}
Juergen Christ via Gcc-cvs <[email protected]>
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:78215710ccafc31fdacc2c6f3080303b5f2d1358 commit r17-2608-g78215710ccafc31fdacc2c6f3080303b5f2d1358 Author: Juergen Christ <[email protected]> Date: Tue Feb 10 14:13:03 2026 +0100 s390x: Implement vec_cbranch_{all,any} 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]> Diff: --- 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/testsuite/gcc.dg/vect/vect-early-break_52.c | 2 +- gcc/testsuite/gcc.dg/vect/vect-early-break_53.c | 2 +- gcc/testsuite/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 4ec9a53f7d76..955cf1ebd603 100644 --- a/gcc/config/s390/s390.cc +++ b/gcc/config/s390/s390.cc @@ -7377,18 +7377,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 @@ -7471,14 +7467,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 205a8d04bdb0..acca6c4ea340 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..50a83093e61a 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_mvx } } } } */ 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..a1fb745ab542 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_mvx } } } } */ + 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..52de4cce69d7 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*-*-* s390x-*-*" } } } } */ 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..49398d00683e 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 { ! s390x-*-* } } } } */ 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..6ce8423df691 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 && { ! s390x-*-* } } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-uncounted_2.c b/gcc/testsuite/gcc.dg/vect/vect-uncounted_2.c index 33fb0ce1f0d0..63e52c86efe1 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 { ! "s390x-*-*" } } } } */ /* { 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 f43197779517..b010d652b9a9 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -4752,6 +4752,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]) }}] } @@ -4769,6 +4771,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]) }}] }