[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])
 	}}]
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.