Generally LGTM I just see some test failures: I guess the following one can be skipped which is dealt with in PR118407: FAIL: gcc.dg/tree-ssa/predcom-8.c scan-tree-dump-not pcom "Invalid sum"
If the target machine does not support VX the following fail: FAIL: gcc.dg/tree-ssa/gen-vect-11.c scan-tree-dump-times vect "vectorized 2 loops" 1 FAIL: gcc.dg/tree-ssa/gen-vect-11a.c scan-tree-dump-times vect "vectorized 2 loops" 1 Test check_effective_target_s390_vx verifies that the machine which we are currently utilizing in order to run the testsuite is able to execute VX instructions. However, this might differ for the target we emit code for. To check also for the target, check_effective_target_s390_mvx is required. Nit: in the target selectors we can now be more specific and refer only to s390x since -m31 is gone. Once the testsuite results are fixed, this is Ok for mainline. Cheers, Stefan On Tue, Jul 07, 2026 at 12:37:17PM +0200, Juergen Christ wrote: > 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 >
