The following example:

#define N 640
int a[N] = {};
int b[N] = {};
int c[N] = {};

void f1 (int d)
{
  for (int i = 0; i < N; i++)
    {
      b[i] += a[i];
      if (a[i] != d)
        break;
    }
}

today generates with
-Ofast -march=armv8-a+sve --param aarch64-autovec-preference=asimd-only

.L6:
        ldr     q30, [x3, x1]
        cmeq    v31.4s, v30.4s, v27.4s
        not     v31.16b, v31.16b
        umaxp   v31.4s, v31.4s, v31.4s
        fmov    x4, d31
        cbz     x4, .L2

Where an we use an Adv. SIMD compare and a reduction sequence to implement
early break.  This patch implements the new optabs vec_cbranch_any and
vec_cbranch_all in order to replace the Adv. SIMD compare and reduction with
an SVE flag-setting compare.

With this patch the above generates:

        ptrue   p7.b, vl16
.L6:
        ldr     q30, [x3, x1]
        cmpne   p15.s, p7/z, z30.s, z27.s
        b.none  .L2

This optab could also be used for optimizing the Adv. SIMD Sequence when SVE
is not available.  I have a separate patch for that and will send depending on
if this approach is accepted or not.

Note that for floating-point we still need the ptest as floating point SVE
compares don't set flags.  In addition because SVE doesn't have a CMTST
equivalent instruction we have to do an explicit AND before the compares.

These two cases don't have a speed advantage, but do have a codesize one
so I've left them enabled.

Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.

Ok for master?

Thanks,
Tamar

gcc/ChangeLog:

        PR target/118974
        * config/aarch64/aarch64-simd.md (<optab><mode>4): New.
        * config/aarch64/aarch64-sve.md (aarch64_ptest<mode>): Rename to..
        (@aarch64_ptest<mode>): ... This.
        * config/aarch64/iterators.md (UNSPEC_CMP_ALL, UNSPEC_CMP_ANY): New.
        (optab): Add them.
        (VALL_PRED, sve_cmp_suff, CBRANCH_CMP, cbranch_op): New.
        (NE):
        * genemit.cc: Include rtx-vector-builder.h.

gcc/testsuite/ChangeLog:

        PR target/118974
        * gcc.target/aarch64/vect-early-break-cbranch_2.c: New test.
        * gcc.target/aarch64/vect-early-break-cbranch_3.c: New test.
        * gcc.target/aarch64/sve/vect-early-break-cbranch_2.c: New test.
        * gcc.target/aarch64/sve/vect-early-break-cbranch_3.c: New test.
        * gcc.target/aarch64/sve/vect-early-break-cbranch_4.c: New test.
        * gcc.target/aarch64/sve/vect-early-break-cbranch_5.c: New test.

---
diff --git a/gcc/config/aarch64/aarch64-simd.md 
b/gcc/config/aarch64/aarch64-simd.md
index 
1099e742cbf7418b75a16ec68f4243fc55e96506..965fab43294ee80d907f2eced820f3cedc0938a6
 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -3952,6 +3952,47 @@ (define_expand "cbranch<mode>4"
   DONE;
 })
 
+;; Define vec_cbranch_any and vec_cbranch_all
+;; Vector comparison and branch for Adv. SIMD types using SVE instructions.
+(define_expand "<optab><mode>4"
+  [(set (pc)
+       (unspec:VALL
+         [(if_then_else
+           (match_operator 0 "aarch64_comparison_operator"
+             [(match_operand:VALL 1 "register_operand")
+              (match_operand:VALL 2 "aarch64_simd_reg_or_zero")])
+           (label_ref (match_operand 3 ""))
+           (pc))]
+        CBRANCH_CMP))]
+  "TARGET_SVE"
+{
+  auto code = GET_CODE (operands[0]);
+  machine_mode full_mode = aarch64_full_sve_mode (<VEL>mode).require ();
+  rtx in1 = force_lowpart_subreg (full_mode, operands[1], <MODE>mode);
+  rtx in2 = force_lowpart_subreg (full_mode, operands[2], <MODE>mode);
+
+  unsigned lanes = exact_div (GET_MODE_BITSIZE (<MODE>mode), 8).to_constant ();
+  machine_mode pred_mode = aarch64_sve_pred_mode (full_mode);
+  rtx_vector_builder builder (VNx16BImode, lanes, 2);
+  for (unsigned int i = 0; i < lanes; ++i)
+    builder.quick_push (CONST1_RTX (BImode));
+  for (unsigned int i = 0; i < lanes; ++i)
+    builder.quick_push (CONST0_RTX (BImode));
+
+  rtx ptrue = force_reg (VNx16BImode, builder.build ());
+  rtx cast_ptrue = gen_lowpart (pred_mode, ptrue);
+  rtx ptrue_flag = gen_int_mode (SVE_KNOWN_PTRUE, SImode);
+
+  rtx tmp = gen_reg_rtx (pred_mode);
+  aarch64_expand_sve_vec_cmp<sve_cmp_suff> (tmp, code, in1, in2);
+  emit_insn (gen_aarch64_ptest (pred_mode, ptrue, cast_ptrue, ptrue_flag, 
tmp));
+
+  rtx cc_reg = gen_rtx_REG (CC_NZCmode, CC_REGNUM);
+  rtx cmp_reg = gen_rtx_<cbranch_op> (VOIDmode, cc_reg, const0_rtx);
+  emit_jump_insn (gen_condjump (cmp_reg, cc_reg, operands[3]));
+  DONE;
+})
+
 ;; Patterns comparing two vectors to produce a mask.
 
 (define_expand "vec_cmp<mode><mode>"
diff --git a/gcc/config/aarch64/aarch64-sve.md 
b/gcc/config/aarch64/aarch64-sve.md
index 
fe7f52ee1ed400b4eda28e3f90edc0044a5aa7a9..4582e12540e93a72fb5baadd77d2470793486346
 100644
--- a/gcc/config/aarch64/aarch64-sve.md
+++ b/gcc/config/aarch64/aarch64-sve.md
@@ -8955,7 +8955,7 @@ (define_expand "cbranch<mode>4"
 )
 
 ;; See "Description of UNSPEC_PTEST" above for details.
-(define_insn "aarch64_ptest<mode>"
+(define_insn "@aarch64_ptest<mode>"
   [(set (reg:CC_NZC CC_REGNUM)
        (unspec:CC_NZC [(match_operand:VNx16BI 0 "register_operand" "Upa")
                        (match_operand 1)
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 
146453b0516848acd40e5f34fd8843fe74c18dbf..9d01305dd63cdba3a5079efbe1680e5715d1a96e
 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -799,6 +799,8 @@ (define_c_enum "unspec"
     UNSPEC_SSHLL       ; Used in aarch64-simd.md.
     UNSPEC_USHLL       ; Used in aarch64-simd.md.
     UNSPEC_ADDP                ; Used in aarch64-simd.md.
+    UNSPEC_CMP_ALL     ; Used in aarch64-simd.md.
+    UNSPEC_CMP_ANY     ; Used in aarch64-simd.md.
     UNSPEC_TBL         ; Used in vector permute patterns.
     UNSPEC_TBLQ                ; Used in vector permute patterns.
     UNSPEC_TBX         ; Used in vector permute patterns.
@@ -2502,6 +2504,19 @@ (define_mode_attr vpred [(VNx16QI "vnx16bi") (VNx8QI 
"vnx8bi")
                         (VNx16SI "vnx4bi") (VNx16SF "vnx4bi")
                         (VNx8DI "vnx2bi") (VNx8DF "vnx2bi")])
 
+;; Map an Adv. SIMD mode to an SVE BI mask that corresponds to the same number
+;; of bits as the Adv. SIMD mode
+(define_mode_attr VALL_PRED [(V8QI "VNx8BI") (V16QI "VNx16BI")
+                            (V4HI "VNx8BI") (V8HI "VNx16BI") (V2SI "VNx8BI")
+                            (V4SI "VNx16BI") (V2DI "VNx16BI")
+                            (V2SF "VNx8BI") (V4SF "VNx16BI") (V2DF "VNx16BI")])
+
+;; Map mode to suffix for using an SVE comparison
+(define_mode_attr sve_cmp_suff [(V8QI "_int") (V16QI "_int")
+                              (V4HI "_int") (V8HI "_int") (V2SI "_int")
+                              (V4SI "_int") (V2DI "_int")
+                              (V2SF "_float") (V4SF "_float") (V2DF "_float")])
+
 (define_mode_attr VDOUBLE [(VNx16QI "VNx32QI")
                           (VNx8HI "VNx16HI") (VNx8HF "VNx16HF")
                           (VNx8BF "VNx16BF")
@@ -3131,6 +3146,8 @@ (define_int_iterator HADD [UNSPEC_SHADD UNSPEC_UHADD])
 
 (define_int_iterator RHADD [UNSPEC_SRHADD UNSPEC_URHADD])
 
+(define_int_iterator CBRANCH_CMP [UNSPEC_CMP_ALL UNSPEC_CMP_ANY])
+
 (define_int_iterator BSL_DUP [1 2])
 
 (define_int_iterator DOTPROD [UNSPEC_SDOT UNSPEC_UDOT])
@@ -4064,7 +4081,11 @@ (define_int_attr optab [(UNSPEC_ANDF "and")
                        (UNSPEC_COND_SCVTF "float")
                        (UNSPEC_COND_SMAX "smax")
                        (UNSPEC_COND_SMIN "smin")
-                       (UNSPEC_COND_UCVTF "floatuns")])
+                       (UNSPEC_COND_UCVTF "floatuns")
+                       (UNSPEC_CMP_ALL "vec_cbranch_all")
+                       (UNSPEC_CMP_ANY "vec_cbranch_any")])
+
+(define_int_attr cbranch_op [(UNSPEC_CMP_ALL "EQ") (UNSPEC_CMP_ANY "NE")])
 
 (define_int_attr fmaxmin [(UNSPEC_FMAX "fmax_nan")
                          (UNSPEC_FMAXNM "fmax")
diff --git a/gcc/genemit.cc b/gcc/genemit.cc
index 
9f92364d9062f7685780a8b0ddc98c4a1c22242b..c69affdb67322d405a887ac0d22652c06e14f19c
 100644
--- a/gcc/genemit.cc
+++ b/gcc/genemit.cc
@@ -907,6 +907,7 @@ from the machine description file `md'.  */\n\n");
   fprintf (file, "#include \"tm-constrs.h\"\n");
   fprintf (file, "#include \"ggc.h\"\n");
   fprintf (file, "#include \"target.h\"\n\n");
+  fprintf (file, "#include \"rtx-vector-builder.h\"\n\n");
 }
 
 auto_vec<FILE *, 10> output_files;
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_2.c 
b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_2.c
new file mode 100644
index 
0000000000000000000000000000000000000000..7c996a893d99f7462c980140d12ab2711738597c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_2.c
@@ -0,0 +1,132 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fno-schedule-insns -fno-reorder-blocks 
-fno-schedule-insns2 --param aarch64-autovec-preference=asimd-only" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdio.h>
+
+#define N 640
+#ifndef TYPE
+#define TYPE int
+#endif
+#ifndef FMT
+#define FMT "d"
+#endif
+
+
+TYPE a[N] = {0};
+TYPE b[N] = {0};
+
+char *curr_test;
+
+/* Macro to define a function with a specific comparison */
+#define DEFINE_TEST_FUNC(NAME, OP)            \
+  __attribute__((noipa))                     \
+  void NAME(void) {                           \
+    for (int i = 0; i < N; i++) {             \
+      b[i] += a[i];                           \
+      if (a[i] OP 0)                          \
+        break;                                \
+    }                                         \
+  }
+
+/* Generate the six comparisons functions using the macro.  */
+DEFINE_TEST_FUNC(f1, >)
+DEFINE_TEST_FUNC(f2, >=)
+DEFINE_TEST_FUNC(f3, ==)
+DEFINE_TEST_FUNC(f4, !=)
+DEFINE_TEST_FUNC(f5, <)
+DEFINE_TEST_FUNC(f6, <=)
+
+__attribute__((noreturn))
+static inline void __abort_trace (const char *m, int i, TYPE result, TYPE 
expected)
+{
+   printf ("*** [%s] FAIL AT %s:%d in %s - expected %" FMT " but got %" FMT " 
at pos %d\n",
+           m, __FILE__, __LINE__, curr_test, expected, result, i);
+   __builtin_abort ();
+}
+
+/* Array setup macro.  */
+#define RESET_ARRAYS(_aval, _idx, _force, _bval)         \
+  do {                                                   \
+    _Pragma("GCC novector")                             \
+    for (int i = 0; i < N; ++i) {                        \
+      a[i] = _aval;                                      \
+      b[i] = _bval;                                      \
+    }                                                    \
+    if (_idx >= 0 && _idx < N)                           \
+      a[_idx] = _force;                                  \
+  } while (0)
+
+/* Value check macros.  */
+#define CHECK_EQ(_i, _val)                        \
+  do {                                            \
+    if (b[_i] != _val)                            \
+      __abort_trace ("single", _i, b[_i], _val);  \
+  } while (0)
+
+#define CHECK_RANGE_EQ(_start, _end, _val)               \
+  do {                                                   \
+    _Pragma("GCC novector")                             \
+    for (int i = _start; i < _end; ++i)                  \
+      if (b[i] != _val)                                  \
+        __abort_trace ("range", i, b[i], _val);          \
+  } while (0)
+
+#define str(s) #s
+#define TEST_FUNC(_func, _aval, _idx, _force, _bval, _check_stmt)  \
+  do {                                                             \
+    curr_test = str (_func);                                       \
+    RESET_ARRAYS((_aval), (_idx), (_force), (_bval));              \
+    _func();                                                       \
+    _check_stmt;                                                   \
+  } while (0)
+
+int main(void) {
+  /* Break on random intervals.  */
+  TEST_FUNC (f1, 1, 0, 1, 10, CHECK_EQ (0, 11); CHECK_EQ (1, 10));
+  TEST_FUNC (f2, -1, 5, 0, 10, CHECK_EQ (0, 9); CHECK_EQ (5, 10));
+  TEST_FUNC (f3, 3, 3, 0, 0, CHECK_EQ (0, 3); CHECK_EQ (3, 0));
+  TEST_FUNC (f4, 0, 4, 1, 1, CHECK_EQ (4, 2); CHECK_EQ (5, 1));
+  TEST_FUNC (f5, 1, 6, -1, 5, CHECK_EQ (6, 4); CHECK_EQ (7, 5));
+  TEST_FUNC (f6, 2, 10, 0, 7, CHECK_EQ (10, 7); CHECK_EQ (11, 7));
+
+  /* Break on last iteration.  */
+  TEST_FUNC (f1, 0, N-1, 1, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 2));
+
+  TEST_FUNC (f2, -5, N-1, 0, 9,
+    CHECK_RANGE_EQ (0, N-1, 4); CHECK_EQ (N-1, 9));
+
+  TEST_FUNC (f3, 2, N-1, 0, 0,
+    CHECK_RANGE_EQ(0, N-1, 2); CHECK_EQ (N-1, 0));
+
+  TEST_FUNC (f4, 0, N-1, 2, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f5, 2, N-1, -3, 6,
+    CHECK_RANGE_EQ (0, N-1, 8); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f6, 5, N-1, 0, 7,
+    CHECK_RANGE_EQ (0, N-1, 12); CHECK_EQ (N-1, 7));
+
+  /* Condition never met — full loop executes.  */
+  TEST_FUNC (f1, 0, -1, 0, 2,
+    CHECK_RANGE_EQ (0, N, 2));
+
+  TEST_FUNC (f2, -2, -1, 0, 5,
+    CHECK_RANGE_EQ (0, N, 3));
+
+  TEST_FUNC (f3, 1, -1, 0, 0,
+    CHECK_RANGE_EQ (0, N, 1));
+
+  TEST_FUNC (f4, 0, -1, 0, 7,
+    CHECK_RANGE_EQ (0, N, 7));
+
+  TEST_FUNC (f5, 1, -1, 0, 4,
+    CHECK_RANGE_EQ (0, N, 5));
+
+  TEST_FUNC (f6, 5, -1, 0, 3,
+    CHECK_RANGE_EQ (0, N, 8));
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_3.c 
b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_3.c
new file mode 100644
index 
0000000000000000000000000000000000000000..75927abb09479712760a60b0f6a11135d9be9502
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_3.c
@@ -0,0 +1,132 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fno-schedule-insns -fno-reorder-blocks 
-fno-schedule-insns2 --param aarch64-autovec-preference=sve-only" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdio.h>
+
+#define N 640
+#ifndef TYPE
+#define TYPE int
+#endif
+#ifndef FMT
+#define FMT "d"
+#endif
+
+
+TYPE a[N] = {0};
+TYPE b[N] = {0};
+
+char *curr_test;
+
+/* Macro to define a function with a specific comparison */
+#define DEFINE_TEST_FUNC(NAME, OP)            \
+  __attribute__((noipa))                     \
+  void NAME(void) {                           \
+    for (int i = 0; i < N; i++) {             \
+      b[i] += a[i];                           \
+      if (a[i] OP 0)                          \
+        break;                                \
+    }                                         \
+  }
+
+/* Generate the six comparisons functions using the macro.  */
+DEFINE_TEST_FUNC(f1, >)
+DEFINE_TEST_FUNC(f2, >=)
+DEFINE_TEST_FUNC(f3, ==)
+DEFINE_TEST_FUNC(f4, !=)
+DEFINE_TEST_FUNC(f5, <)
+DEFINE_TEST_FUNC(f6, <=)
+
+__attribute__((noreturn))
+static inline void __abort_trace (const char *m, int i, TYPE result, TYPE 
expected)
+{
+   printf ("*** [%s] FAIL AT %s:%d in %s - expected %" FMT " but got %" FMT " 
at pos %d\n",
+           m, __FILE__, __LINE__, curr_test, expected, result, i);
+   __builtin_abort ();
+}
+
+/* Array setup macro.  */
+#define RESET_ARRAYS(_aval, _idx, _force, _bval)         \
+  do {                                                   \
+    _Pragma("GCC novector")                             \
+    for (int i = 0; i < N; ++i) {                        \
+      a[i] = _aval;                                      \
+      b[i] = _bval;                                      \
+    }                                                    \
+    if (_idx >= 0 && _idx < N)                           \
+      a[_idx] = _force;                                  \
+  } while (0)
+
+/* Value check macros.  */
+#define CHECK_EQ(_i, _val)                        \
+  do {                                            \
+    if (b[_i] != _val)                            \
+      __abort_trace ("single", _i, b[_i], _val);  \
+  } while (0)
+
+#define CHECK_RANGE_EQ(_start, _end, _val)               \
+  do {                                                   \
+    _Pragma("GCC novector")                             \
+    for (int i = _start; i < _end; ++i)                  \
+      if (b[i] != _val)                                  \
+        __abort_trace ("range", i, b[i], _val);          \
+  } while (0)
+
+#define str(s) #s
+#define TEST_FUNC(_func, _aval, _idx, _force, _bval, _check_stmt)  \
+  do {                                                             \
+    curr_test = str (_func);                                       \
+    RESET_ARRAYS((_aval), (_idx), (_force), (_bval));              \
+    _func();                                                       \
+    _check_stmt;                                                   \
+  } while (0)
+
+int main(void) {
+  /* Break on random intervals.  */
+  TEST_FUNC (f1, 1, 0, 1, 10, CHECK_EQ (0, 11); CHECK_EQ (1, 10));
+  TEST_FUNC (f2, -1, 5, 0, 10, CHECK_EQ (0, 9); CHECK_EQ (5, 10));
+  TEST_FUNC (f3, 3, 3, 0, 0, CHECK_EQ (0, 3); CHECK_EQ (3, 0));
+  TEST_FUNC (f4, 0, 4, 1, 1, CHECK_EQ (4, 2); CHECK_EQ (5, 1));
+  TEST_FUNC (f5, 1, 6, -1, 5, CHECK_EQ (6, 4); CHECK_EQ (7, 5));
+  TEST_FUNC (f6, 2, 10, 0, 7, CHECK_EQ (10, 7); CHECK_EQ (11, 7));
+
+  /* Break on last iteration.  */
+  TEST_FUNC (f1, 0, N-1, 1, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 2));
+
+  TEST_FUNC (f2, -5, N-1, 0, 9,
+    CHECK_RANGE_EQ (0, N-1, 4); CHECK_EQ (N-1, 9));
+
+  TEST_FUNC (f3, 2, N-1, 0, 0,
+    CHECK_RANGE_EQ(0, N-1, 2); CHECK_EQ (N-1, 0));
+
+  TEST_FUNC (f4, 0, N-1, 2, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f5, 2, N-1, -3, 6,
+    CHECK_RANGE_EQ (0, N-1, 8); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f6, 5, N-1, 0, 7,
+    CHECK_RANGE_EQ (0, N-1, 12); CHECK_EQ (N-1, 7));
+
+  /* Condition never met — full loop executes.  */
+  TEST_FUNC (f1, 0, -1, 0, 2,
+    CHECK_RANGE_EQ (0, N, 2));
+
+  TEST_FUNC (f2, -2, -1, 0, 5,
+    CHECK_RANGE_EQ (0, N, 3));
+
+  TEST_FUNC (f3, 1, -1, 0, 0,
+    CHECK_RANGE_EQ (0, N, 1));
+
+  TEST_FUNC (f4, 0, -1, 0, 7,
+    CHECK_RANGE_EQ (0, N, 7));
+
+  TEST_FUNC (f5, 1, -1, 0, 4,
+    CHECK_RANGE_EQ (0, N, 5));
+
+  TEST_FUNC (f6, 5, -1, 0, 3,
+    CHECK_RANGE_EQ (0, N, 8));
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_4.c 
b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_4.c
new file mode 100644
index 
0000000000000000000000000000000000000000..68a5d0a09fdfd5664562e1bac3b5e586a37b3a6f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_4.c
@@ -0,0 +1,132 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fno-schedule-insns -fno-reorder-blocks 
-fno-schedule-insns2 --param aarch64-autovec-preference=asimd-only" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdio.h>
+
+#define N 640
+#ifndef TYPE
+#define TYPE float
+#endif
+#ifndef FMT
+#define FMT ".6f"
+#endif
+
+
+TYPE a[N] = {0};
+TYPE b[N] = {0};
+
+char *curr_test;
+
+/* Macro to define a function with a specific comparison */
+#define DEFINE_TEST_FUNC(NAME, OP)            \
+  __attribute__((noipa))                     \
+  void NAME(void) {                           \
+    for (int i = 0; i < N; i++) {             \
+      b[i] += a[i];                           \
+      if (a[i] OP 0)                          \
+        break;                                \
+    }                                         \
+  }
+
+/* Generate the six comparisons functions using the macro.  */
+DEFINE_TEST_FUNC(f1, >)
+DEFINE_TEST_FUNC(f2, >=)
+DEFINE_TEST_FUNC(f3, ==)
+DEFINE_TEST_FUNC(f4, !=)
+DEFINE_TEST_FUNC(f5, <)
+DEFINE_TEST_FUNC(f6, <=)
+
+__attribute__((noreturn))
+static inline void __abort_trace (const char *m, int i, TYPE result, TYPE 
expected)
+{
+   printf ("*** [%s] FAIL AT %s:%d in %s - expected %" FMT " but got %" FMT " 
at pos %d\n",
+           m, __FILE__, __LINE__, curr_test, expected, result, i);
+   __builtin_abort ();
+}
+
+/* Array setup macro.  */
+#define RESET_ARRAYS(_aval, _idx, _force, _bval)         \
+  do {                                                   \
+    _Pragma("GCC novector")                             \
+    for (int i = 0; i < N; ++i) {                        \
+      a[i] = _aval;                                      \
+      b[i] = _bval;                                      \
+    }                                                    \
+    if (_idx >= 0 && _idx < N)                           \
+      a[_idx] = _force;                                  \
+  } while (0)
+
+/* Value check macros.  */
+#define CHECK_EQ(_i, _val)                        \
+  do {                                            \
+    if (b[_i] != _val)                            \
+      __abort_trace ("single", _i, b[_i], _val);  \
+  } while (0)
+
+#define CHECK_RANGE_EQ(_start, _end, _val)               \
+  do {                                                   \
+    _Pragma("GCC novector")                             \
+    for (int i = _start; i < _end; ++i)                  \
+      if (b[i] != _val)                                  \
+        __abort_trace ("range", i, b[i], _val);          \
+  } while (0)
+
+#define str(s) #s
+#define TEST_FUNC(_func, _aval, _idx, _force, _bval, _check_stmt)  \
+  do {                                                             \
+    curr_test = str (_func);                                       \
+    RESET_ARRAYS((_aval), (_idx), (_force), (_bval));              \
+    _func();                                                       \
+    _check_stmt;                                                   \
+  } while (0)
+
+int main(void) {
+  /* Break on random intervals.  */
+  TEST_FUNC (f1, 1, 0, 1, 10, CHECK_EQ (0, 11); CHECK_EQ (1, 10));
+  TEST_FUNC (f2, -1, 5, 0, 10, CHECK_EQ (0, 9); CHECK_EQ (5, 10));
+  TEST_FUNC (f3, 3, 3, 0, 0, CHECK_EQ (0, 3); CHECK_EQ (3, 0));
+  TEST_FUNC (f4, 0, 4, 1, 1, CHECK_EQ (4, 2); CHECK_EQ (5, 1));
+  TEST_FUNC (f5, 1, 6, -1, 5, CHECK_EQ (6, 4); CHECK_EQ (7, 5));
+  TEST_FUNC (f6, 2, 10, 0, 7, CHECK_EQ (10, 7); CHECK_EQ (11, 7));
+
+  /* Break on last iteration.  */
+  TEST_FUNC (f1, 0, N-1, 1, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 2));
+
+  TEST_FUNC (f2, -5, N-1, 0, 9,
+    CHECK_RANGE_EQ (0, N-1, 4); CHECK_EQ (N-1, 9));
+
+  TEST_FUNC (f3, 2, N-1, 0, 0,
+    CHECK_RANGE_EQ(0, N-1, 2); CHECK_EQ (N-1, 0));
+
+  TEST_FUNC (f4, 0, N-1, 2, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f5, 2, N-1, -3, 6,
+    CHECK_RANGE_EQ (0, N-1, 8); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f6, 5, N-1, 0, 7,
+    CHECK_RANGE_EQ (0, N-1, 12); CHECK_EQ (N-1, 7));
+
+  /* Condition never met — full loop executes.  */
+  TEST_FUNC (f1, 0, -1, 0, 2,
+    CHECK_RANGE_EQ (0, N, 2));
+
+  TEST_FUNC (f2, -2, -1, 0, 5,
+    CHECK_RANGE_EQ (0, N, 3));
+
+  TEST_FUNC (f3, 1, -1, 0, 0,
+    CHECK_RANGE_EQ (0, N, 1));
+
+  TEST_FUNC (f4, 0, -1, 0, 7,
+    CHECK_RANGE_EQ (0, N, 7));
+
+  TEST_FUNC (f5, 1, -1, 0, 4,
+    CHECK_RANGE_EQ (0, N, 5));
+
+  TEST_FUNC (f6, 5, -1, 0, 3,
+    CHECK_RANGE_EQ (0, N, 8));
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_5.c 
b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_5.c
new file mode 100644
index 
0000000000000000000000000000000000000000..52d95e9a71b7999376731e47a224936d4253ac2f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_5.c
@@ -0,0 +1,132 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fno-schedule-insns -fno-reorder-blocks 
-fno-schedule-insns2 --param aarch64-autovec-preference=sve-only" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdio.h>
+
+#define N 640
+#ifndef TYPE
+#define TYPE float
+#endif
+#ifndef FMT
+#define FMT ".6f"
+#endif
+
+
+TYPE a[N] = {0};
+TYPE b[N] = {0};
+
+char *curr_test;
+
+/* Macro to define a function with a specific comparison */
+#define DEFINE_TEST_FUNC(NAME, OP)            \
+  __attribute__((noipa))                     \
+  void NAME(void) {                           \
+    for (int i = 0; i < N; i++) {             \
+      b[i] += a[i];                           \
+      if (a[i] OP 0)                          \
+        break;                                \
+    }                                         \
+  }
+
+/* Generate the six comparisons functions using the macro.  */
+DEFINE_TEST_FUNC(f1, >)
+DEFINE_TEST_FUNC(f2, >=)
+DEFINE_TEST_FUNC(f3, ==)
+DEFINE_TEST_FUNC(f4, !=)
+DEFINE_TEST_FUNC(f5, <)
+DEFINE_TEST_FUNC(f6, <=)
+
+__attribute__((noreturn))
+static inline void __abort_trace (const char *m, int i, TYPE result, TYPE 
expected)
+{
+   printf ("*** [%s] FAIL AT %s:%d in %s - expected %" FMT " but got %" FMT " 
at pos %d\n",
+           m, __FILE__, __LINE__, curr_test, expected, result, i);
+   __builtin_abort ();
+}
+
+/* Array setup macro.  */
+#define RESET_ARRAYS(_aval, _idx, _force, _bval)         \
+  do {                                                   \
+    _Pragma("GCC novector")                             \
+    for (int i = 0; i < N; ++i) {                        \
+      a[i] = _aval;                                      \
+      b[i] = _bval;                                      \
+    }                                                    \
+    if (_idx >= 0 && _idx < N)                           \
+      a[_idx] = _force;                                  \
+  } while (0)
+
+/* Value check macros.  */
+#define CHECK_EQ(_i, _val)                        \
+  do {                                            \
+    if (b[_i] != _val)                            \
+      __abort_trace ("single", _i, b[_i], _val);  \
+  } while (0)
+
+#define CHECK_RANGE_EQ(_start, _end, _val)               \
+  do {                                                   \
+    _Pragma("GCC novector")                             \
+    for (int i = _start; i < _end; ++i)                  \
+      if (b[i] != _val)                                  \
+        __abort_trace ("range", i, b[i], _val);          \
+  } while (0)
+
+#define str(s) #s
+#define TEST_FUNC(_func, _aval, _idx, _force, _bval, _check_stmt)  \
+  do {                                                             \
+    curr_test = str (_func);                                       \
+    RESET_ARRAYS((_aval), (_idx), (_force), (_bval));              \
+    _func();                                                       \
+    _check_stmt;                                                   \
+  } while (0)
+
+int main(void) {
+  /* Break on random intervals.  */
+  TEST_FUNC (f1, 1, 0, 1, 10, CHECK_EQ (0, 11); CHECK_EQ (1, 10));
+  TEST_FUNC (f2, -1, 5, 0, 10, CHECK_EQ (0, 9); CHECK_EQ (5, 10));
+  TEST_FUNC (f3, 3, 3, 0, 0, CHECK_EQ (0, 3); CHECK_EQ (3, 0));
+  TEST_FUNC (f4, 0, 4, 1, 1, CHECK_EQ (4, 2); CHECK_EQ (5, 1));
+  TEST_FUNC (f5, 1, 6, -1, 5, CHECK_EQ (6, 4); CHECK_EQ (7, 5));
+  TEST_FUNC (f6, 2, 10, 0, 7, CHECK_EQ (10, 7); CHECK_EQ (11, 7));
+
+  /* Break on last iteration.  */
+  TEST_FUNC (f1, 0, N-1, 1, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 2));
+
+  TEST_FUNC (f2, -5, N-1, 0, 9,
+    CHECK_RANGE_EQ (0, N-1, 4); CHECK_EQ (N-1, 9));
+
+  TEST_FUNC (f3, 2, N-1, 0, 0,
+    CHECK_RANGE_EQ(0, N-1, 2); CHECK_EQ (N-1, 0));
+
+  TEST_FUNC (f4, 0, N-1, 2, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f5, 2, N-1, -3, 6,
+    CHECK_RANGE_EQ (0, N-1, 8); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f6, 5, N-1, 0, 7,
+    CHECK_RANGE_EQ (0, N-1, 12); CHECK_EQ (N-1, 7));
+
+  /* Condition never met — full loop executes.  */
+  TEST_FUNC (f1, 0, -1, 0, 2,
+    CHECK_RANGE_EQ (0, N, 2));
+
+  TEST_FUNC (f2, -2, -1, 0, 5,
+    CHECK_RANGE_EQ (0, N, 3));
+
+  TEST_FUNC (f3, 1, -1, 0, 0,
+    CHECK_RANGE_EQ (0, N, 1));
+
+  TEST_FUNC (f4, 0, -1, 0, 7,
+    CHECK_RANGE_EQ (0, N, 7));
+
+  TEST_FUNC (f5, 1, -1, 0, 4,
+    CHECK_RANGE_EQ (0, N, 5));
+
+  TEST_FUNC (f6, 5, -1, 0, 3,
+    CHECK_RANGE_EQ (0, N, 8));
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_2.c 
b/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_2.c
new file mode 100644
index 
0000000000000000000000000000000000000000..218349311d9044c0c0c195c72b0cc6ad43022448
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_2.c
@@ -0,0 +1,105 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-schedule-insns -fno-reorder-blocks 
-fno-schedule-insns2 --param aarch64-autovec-preference=asimd-only" } */
+/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */
+
+#pragma GCC target "+sve"
+
+#define N 640
+int a[N] = {0};
+int b[N] = {0};
+/*
+** f1:
+**     ...
+**     cmpgt   p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0
+**     b.none  \.L[0-9]+
+**     ...
+*/
+void f1 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] > 0)
+       break;
+    }
+}
+/*
+** f2:
+**     ...
+**     cmpge   p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0
+**     b.none  \.L[0-9]+
+**     ...
+*/
+void f2 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] >= 0)
+       break;
+    }
+}
+/*
+** f3:
+**     ...
+**     cmpeq   p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0
+**     b.none  \.L[0-9]+
+**     ...
+*/
+void f3 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] == 0)
+       break;
+    }
+}
+/*
+** f4:
+**     ...
+**     cmpne   p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0
+**     b.none  \.L[0-9]+
+**     ...
+*/
+void f4 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] != 0)
+       break;
+    }
+}
+/*
+** f5:
+**     ...
+**     cmplt   p[0-9]+.s, p7/z, z[0-9]+.s, #0
+**     b.none  .L[0-9]+
+**     ...
+*/
+void f5 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] < 0)
+       break;
+    }
+}
+/*
+** f6:
+**     ...
+**     cmple   p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0
+**     b.none  \.L[0-9]+
+**     ...
+*/
+void f6 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] <= 0)
+       break;
+    }
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_3.c 
b/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_3.c
new file mode 100644
index 
0000000000000000000000000000000000000000..d4885b02c4a4c1338119c05bf812cfa521c3515b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_3.c
@@ -0,0 +1,112 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-schedule-insns -fno-reorder-blocks 
-fno-schedule-insns2 --param aarch64-autovec-preference=asimd-only" } */
+/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */
+
+#pragma GCC target "+sve"
+
+#define N 640
+float a[N] = {0};
+float b[N] = {0};
+
+/*
+** f1:
+**     ...
+**     fcmgt   p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0.0
+**     ptest   p[0-9]+, p[0-9]+\.b
+**     b.none  \.L[0-9]+
+**     ...
+*/
+void f1 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] > 0)
+       break;
+    }
+}
+/*
+** f2:
+**     ...
+**     fcmge   p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0.0
+**     ptest   p[0-9]+, p[0-9]+\.b
+**     b.none  \.L[0-9]+
+**     ...
+*/
+void f2 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] >= 0)
+       break;
+    }
+}
+/*
+** f3:
+**     ...
+**     fcmeq   p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0.0
+**     ptest   p[0-9]+, p[0-9]+\.b
+**     b.none  \.L[0-9]+
+**     ...
+*/
+void f3 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] == 0)
+       break;
+    }
+}
+/*
+** f4:
+**     ...
+**     fcmne   p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0.0
+**     ptest   p[0-9]+, p[0-9]+\.b
+**     b.none  \.L[0-9]+
+**     ...
+*/
+void f4 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] != 0)
+       break;
+    }
+}
+/*
+** f5:
+**     ...
+**     fcmlt   p[0-9]+.s, p7/z, z[0-9]+.s, #0.0
+**     ptest   p[0-9]+, p[0-9]+\.b
+**     b.none  .L[0-9]+
+**     ...
+*/
+void f5 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] < 0)
+       break;
+    }
+}
+/*
+** f6:
+**     ...
+**     fcmle   p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0.0
+**     ptest   p[0-9]+, p[0-9]+\.b
+**     b.none  \.L[0-9]+
+**     ...
+*/
+void f6 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] <= 0)
+       break;
+    }
+}


-- 
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index 1099e742cbf7418b75a16ec68f4243fc55e96506..965fab43294ee80d907f2eced820f3cedc0938a6 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -3952,6 +3952,47 @@ (define_expand "cbranch<mode>4"
   DONE;
 })
 
+;; Define vec_cbranch_any and vec_cbranch_all
+;; Vector comparison and branch for Adv. SIMD types using SVE instructions.
+(define_expand "<optab><mode>4"
+  [(set (pc)
+	(unspec:VALL
+	  [(if_then_else
+	    (match_operator 0 "aarch64_comparison_operator"
+	      [(match_operand:VALL 1 "register_operand")
+	       (match_operand:VALL 2 "aarch64_simd_reg_or_zero")])
+	    (label_ref (match_operand 3 ""))
+	    (pc))]
+	 CBRANCH_CMP))]
+  "TARGET_SVE"
+{
+  auto code = GET_CODE (operands[0]);
+  machine_mode full_mode = aarch64_full_sve_mode (<VEL>mode).require ();
+  rtx in1 = force_lowpart_subreg (full_mode, operands[1], <MODE>mode);
+  rtx in2 = force_lowpart_subreg (full_mode, operands[2], <MODE>mode);
+
+  unsigned lanes = exact_div (GET_MODE_BITSIZE (<MODE>mode), 8).to_constant ();
+  machine_mode pred_mode = aarch64_sve_pred_mode (full_mode);
+  rtx_vector_builder builder (VNx16BImode, lanes, 2);
+  for (unsigned int i = 0; i < lanes; ++i)
+    builder.quick_push (CONST1_RTX (BImode));
+  for (unsigned int i = 0; i < lanes; ++i)
+    builder.quick_push (CONST0_RTX (BImode));
+
+  rtx ptrue = force_reg (VNx16BImode, builder.build ());
+  rtx cast_ptrue = gen_lowpart (pred_mode, ptrue);
+  rtx ptrue_flag = gen_int_mode (SVE_KNOWN_PTRUE, SImode);
+
+  rtx tmp = gen_reg_rtx (pred_mode);
+  aarch64_expand_sve_vec_cmp<sve_cmp_suff> (tmp, code, in1, in2);
+  emit_insn (gen_aarch64_ptest (pred_mode, ptrue, cast_ptrue, ptrue_flag, tmp));
+
+  rtx cc_reg = gen_rtx_REG (CC_NZCmode, CC_REGNUM);
+  rtx cmp_reg = gen_rtx_<cbranch_op> (VOIDmode, cc_reg, const0_rtx);
+  emit_jump_insn (gen_condjump (cmp_reg, cc_reg, operands[3]));
+  DONE;
+})
+
 ;; Patterns comparing two vectors to produce a mask.
 
 (define_expand "vec_cmp<mode><mode>"
diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md
index fe7f52ee1ed400b4eda28e3f90edc0044a5aa7a9..4582e12540e93a72fb5baadd77d2470793486346 100644
--- a/gcc/config/aarch64/aarch64-sve.md
+++ b/gcc/config/aarch64/aarch64-sve.md
@@ -8955,7 +8955,7 @@ (define_expand "cbranch<mode>4"
 )
 
 ;; See "Description of UNSPEC_PTEST" above for details.
-(define_insn "aarch64_ptest<mode>"
+(define_insn "@aarch64_ptest<mode>"
   [(set (reg:CC_NZC CC_REGNUM)
 	(unspec:CC_NZC [(match_operand:VNx16BI 0 "register_operand" "Upa")
 			(match_operand 1)
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 146453b0516848acd40e5f34fd8843fe74c18dbf..9d01305dd63cdba3a5079efbe1680e5715d1a96e 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -799,6 +799,8 @@ (define_c_enum "unspec"
     UNSPEC_SSHLL	; Used in aarch64-simd.md.
     UNSPEC_USHLL	; Used in aarch64-simd.md.
     UNSPEC_ADDP		; Used in aarch64-simd.md.
+    UNSPEC_CMP_ALL	; Used in aarch64-simd.md.
+    UNSPEC_CMP_ANY	; Used in aarch64-simd.md.
     UNSPEC_TBL		; Used in vector permute patterns.
     UNSPEC_TBLQ		; Used in vector permute patterns.
     UNSPEC_TBX		; Used in vector permute patterns.
@@ -2502,6 +2504,19 @@ (define_mode_attr vpred [(VNx16QI "vnx16bi") (VNx8QI "vnx8bi")
 			 (VNx16SI "vnx4bi") (VNx16SF "vnx4bi")
 			 (VNx8DI "vnx2bi") (VNx8DF "vnx2bi")])
 
+;; Map an Adv. SIMD mode to an SVE BI mask that corresponds to the same number
+;; of bits as the Adv. SIMD mode
+(define_mode_attr VALL_PRED [(V8QI "VNx8BI") (V16QI "VNx16BI")
+			     (V4HI "VNx8BI") (V8HI "VNx16BI") (V2SI "VNx8BI")
+			     (V4SI "VNx16BI") (V2DI "VNx16BI")
+			     (V2SF "VNx8BI") (V4SF "VNx16BI") (V2DF "VNx16BI")])
+
+;; Map mode to suffix for using an SVE comparison
+(define_mode_attr sve_cmp_suff [(V8QI "_int") (V16QI "_int")
+			       (V4HI "_int") (V8HI "_int") (V2SI "_int")
+			       (V4SI "_int") (V2DI "_int")
+			       (V2SF "_float") (V4SF "_float") (V2DF "_float")])
+
 (define_mode_attr VDOUBLE [(VNx16QI "VNx32QI")
 			   (VNx8HI "VNx16HI") (VNx8HF "VNx16HF")
 			   (VNx8BF "VNx16BF")
@@ -3131,6 +3146,8 @@ (define_int_iterator HADD [UNSPEC_SHADD UNSPEC_UHADD])
 
 (define_int_iterator RHADD [UNSPEC_SRHADD UNSPEC_URHADD])
 
+(define_int_iterator CBRANCH_CMP [UNSPEC_CMP_ALL UNSPEC_CMP_ANY])
+
 (define_int_iterator BSL_DUP [1 2])
 
 (define_int_iterator DOTPROD [UNSPEC_SDOT UNSPEC_UDOT])
@@ -4064,7 +4081,11 @@ (define_int_attr optab [(UNSPEC_ANDF "and")
 			(UNSPEC_COND_SCVTF "float")
 			(UNSPEC_COND_SMAX "smax")
 			(UNSPEC_COND_SMIN "smin")
-			(UNSPEC_COND_UCVTF "floatuns")])
+			(UNSPEC_COND_UCVTF "floatuns")
+			(UNSPEC_CMP_ALL "vec_cbranch_all")
+			(UNSPEC_CMP_ANY "vec_cbranch_any")])
+
+(define_int_attr cbranch_op [(UNSPEC_CMP_ALL "EQ") (UNSPEC_CMP_ANY "NE")])
 
 (define_int_attr fmaxmin [(UNSPEC_FMAX "fmax_nan")
 			  (UNSPEC_FMAXNM "fmax")
diff --git a/gcc/genemit.cc b/gcc/genemit.cc
index 9f92364d9062f7685780a8b0ddc98c4a1c22242b..c69affdb67322d405a887ac0d22652c06e14f19c 100644
--- a/gcc/genemit.cc
+++ b/gcc/genemit.cc
@@ -907,6 +907,7 @@ from the machine description file `md'.  */\n\n");
   fprintf (file, "#include \"tm-constrs.h\"\n");
   fprintf (file, "#include \"ggc.h\"\n");
   fprintf (file, "#include \"target.h\"\n\n");
+  fprintf (file, "#include \"rtx-vector-builder.h\"\n\n");
 }
 
 auto_vec<FILE *, 10> output_files;
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_2.c b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_2.c
new file mode 100644
index 0000000000000000000000000000000000000000..7c996a893d99f7462c980140d12ab2711738597c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_2.c
@@ -0,0 +1,132 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fno-schedule-insns -fno-reorder-blocks -fno-schedule-insns2 --param aarch64-autovec-preference=asimd-only" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdio.h>
+
+#define N 640
+#ifndef TYPE
+#define TYPE int
+#endif
+#ifndef FMT
+#define FMT "d"
+#endif
+
+
+TYPE a[N] = {0};
+TYPE b[N] = {0};
+
+char *curr_test;
+
+/* Macro to define a function with a specific comparison */
+#define DEFINE_TEST_FUNC(NAME, OP)            \
+  __attribute__((noipa))		      \
+  void NAME(void) {                           \
+    for (int i = 0; i < N; i++) {             \
+      b[i] += a[i];                           \
+      if (a[i] OP 0)                          \
+        break;                                \
+    }                                         \
+  }
+
+/* Generate the six comparisons functions using the macro.  */
+DEFINE_TEST_FUNC(f1, >)
+DEFINE_TEST_FUNC(f2, >=)
+DEFINE_TEST_FUNC(f3, ==)
+DEFINE_TEST_FUNC(f4, !=)
+DEFINE_TEST_FUNC(f5, <)
+DEFINE_TEST_FUNC(f6, <=)
+
+__attribute__((noreturn))
+static inline void __abort_trace (const char *m, int i, TYPE result, TYPE expected)
+{
+   printf ("*** [%s] FAIL AT %s:%d in %s - expected %" FMT " but got %" FMT " at pos %d\n",
+           m, __FILE__, __LINE__, curr_test, expected, result, i);
+   __builtin_abort ();
+}
+
+/* Array setup macro.  */
+#define RESET_ARRAYS(_aval, _idx, _force, _bval)         \
+  do {                                                   \
+    _Pragma("GCC novector")				 \
+    for (int i = 0; i < N; ++i) {                        \
+      a[i] = _aval;                                      \
+      b[i] = _bval;                                      \
+    }                                                    \
+    if (_idx >= 0 && _idx < N)                           \
+      a[_idx] = _force;                                  \
+  } while (0)
+
+/* Value check macros.  */
+#define CHECK_EQ(_i, _val)                        \
+  do {                                            \
+    if (b[_i] != _val)                            \
+      __abort_trace ("single", _i, b[_i], _val);  \
+  } while (0)
+
+#define CHECK_RANGE_EQ(_start, _end, _val)               \
+  do {                                                   \
+    _Pragma("GCC novector")				 \
+    for (int i = _start; i < _end; ++i)                  \
+      if (b[i] != _val)                                  \
+        __abort_trace ("range", i, b[i], _val);          \
+  } while (0)
+
+#define str(s) #s
+#define TEST_FUNC(_func, _aval, _idx, _force, _bval, _check_stmt)  \
+  do {                                                             \
+    curr_test = str (_func);                                       \
+    RESET_ARRAYS((_aval), (_idx), (_force), (_bval));              \
+    _func();                                                       \
+    _check_stmt;                                                   \
+  } while (0)
+
+int main(void) {
+  /* Break on random intervals.  */
+  TEST_FUNC (f1, 1, 0, 1, 10, CHECK_EQ (0, 11); CHECK_EQ (1, 10));
+  TEST_FUNC (f2, -1, 5, 0, 10, CHECK_EQ (0, 9); CHECK_EQ (5, 10));
+  TEST_FUNC (f3, 3, 3, 0, 0, CHECK_EQ (0, 3); CHECK_EQ (3, 0));
+  TEST_FUNC (f4, 0, 4, 1, 1, CHECK_EQ (4, 2); CHECK_EQ (5, 1));
+  TEST_FUNC (f5, 1, 6, -1, 5, CHECK_EQ (6, 4); CHECK_EQ (7, 5));
+  TEST_FUNC (f6, 2, 10, 0, 7, CHECK_EQ (10, 7); CHECK_EQ (11, 7));
+
+  /* Break on last iteration.  */
+  TEST_FUNC (f1, 0, N-1, 1, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 2));
+
+  TEST_FUNC (f2, -5, N-1, 0, 9,
+    CHECK_RANGE_EQ (0, N-1, 4); CHECK_EQ (N-1, 9));
+
+  TEST_FUNC (f3, 2, N-1, 0, 0,
+    CHECK_RANGE_EQ(0, N-1, 2); CHECK_EQ (N-1, 0));
+
+  TEST_FUNC (f4, 0, N-1, 2, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f5, 2, N-1, -3, 6,
+    CHECK_RANGE_EQ (0, N-1, 8); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f6, 5, N-1, 0, 7,
+    CHECK_RANGE_EQ (0, N-1, 12); CHECK_EQ (N-1, 7));
+
+  /* Condition never met — full loop executes.  */
+  TEST_FUNC (f1, 0, -1, 0, 2,
+    CHECK_RANGE_EQ (0, N, 2));
+
+  TEST_FUNC (f2, -2, -1, 0, 5,
+    CHECK_RANGE_EQ (0, N, 3));
+
+  TEST_FUNC (f3, 1, -1, 0, 0,
+    CHECK_RANGE_EQ (0, N, 1));
+
+  TEST_FUNC (f4, 0, -1, 0, 7,
+    CHECK_RANGE_EQ (0, N, 7));
+
+  TEST_FUNC (f5, 1, -1, 0, 4,
+    CHECK_RANGE_EQ (0, N, 5));
+
+  TEST_FUNC (f6, 5, -1, 0, 3,
+    CHECK_RANGE_EQ (0, N, 8));
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_3.c b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_3.c
new file mode 100644
index 0000000000000000000000000000000000000000..75927abb09479712760a60b0f6a11135d9be9502
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_3.c
@@ -0,0 +1,132 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fno-schedule-insns -fno-reorder-blocks -fno-schedule-insns2 --param aarch64-autovec-preference=sve-only" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdio.h>
+
+#define N 640
+#ifndef TYPE
+#define TYPE int
+#endif
+#ifndef FMT
+#define FMT "d"
+#endif
+
+
+TYPE a[N] = {0};
+TYPE b[N] = {0};
+
+char *curr_test;
+
+/* Macro to define a function with a specific comparison */
+#define DEFINE_TEST_FUNC(NAME, OP)            \
+  __attribute__((noipa))		      \
+  void NAME(void) {                           \
+    for (int i = 0; i < N; i++) {             \
+      b[i] += a[i];                           \
+      if (a[i] OP 0)                          \
+        break;                                \
+    }                                         \
+  }
+
+/* Generate the six comparisons functions using the macro.  */
+DEFINE_TEST_FUNC(f1, >)
+DEFINE_TEST_FUNC(f2, >=)
+DEFINE_TEST_FUNC(f3, ==)
+DEFINE_TEST_FUNC(f4, !=)
+DEFINE_TEST_FUNC(f5, <)
+DEFINE_TEST_FUNC(f6, <=)
+
+__attribute__((noreturn))
+static inline void __abort_trace (const char *m, int i, TYPE result, TYPE expected)
+{
+   printf ("*** [%s] FAIL AT %s:%d in %s - expected %" FMT " but got %" FMT " at pos %d\n",
+           m, __FILE__, __LINE__, curr_test, expected, result, i);
+   __builtin_abort ();
+}
+
+/* Array setup macro.  */
+#define RESET_ARRAYS(_aval, _idx, _force, _bval)         \
+  do {                                                   \
+    _Pragma("GCC novector")				 \
+    for (int i = 0; i < N; ++i) {                        \
+      a[i] = _aval;                                      \
+      b[i] = _bval;                                      \
+    }                                                    \
+    if (_idx >= 0 && _idx < N)                           \
+      a[_idx] = _force;                                  \
+  } while (0)
+
+/* Value check macros.  */
+#define CHECK_EQ(_i, _val)                        \
+  do {                                            \
+    if (b[_i] != _val)                            \
+      __abort_trace ("single", _i, b[_i], _val);  \
+  } while (0)
+
+#define CHECK_RANGE_EQ(_start, _end, _val)               \
+  do {                                                   \
+    _Pragma("GCC novector")				 \
+    for (int i = _start; i < _end; ++i)                  \
+      if (b[i] != _val)                                  \
+        __abort_trace ("range", i, b[i], _val);          \
+  } while (0)
+
+#define str(s) #s
+#define TEST_FUNC(_func, _aval, _idx, _force, _bval, _check_stmt)  \
+  do {                                                             \
+    curr_test = str (_func);                                       \
+    RESET_ARRAYS((_aval), (_idx), (_force), (_bval));              \
+    _func();                                                       \
+    _check_stmt;                                                   \
+  } while (0)
+
+int main(void) {
+  /* Break on random intervals.  */
+  TEST_FUNC (f1, 1, 0, 1, 10, CHECK_EQ (0, 11); CHECK_EQ (1, 10));
+  TEST_FUNC (f2, -1, 5, 0, 10, CHECK_EQ (0, 9); CHECK_EQ (5, 10));
+  TEST_FUNC (f3, 3, 3, 0, 0, CHECK_EQ (0, 3); CHECK_EQ (3, 0));
+  TEST_FUNC (f4, 0, 4, 1, 1, CHECK_EQ (4, 2); CHECK_EQ (5, 1));
+  TEST_FUNC (f5, 1, 6, -1, 5, CHECK_EQ (6, 4); CHECK_EQ (7, 5));
+  TEST_FUNC (f6, 2, 10, 0, 7, CHECK_EQ (10, 7); CHECK_EQ (11, 7));
+
+  /* Break on last iteration.  */
+  TEST_FUNC (f1, 0, N-1, 1, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 2));
+
+  TEST_FUNC (f2, -5, N-1, 0, 9,
+    CHECK_RANGE_EQ (0, N-1, 4); CHECK_EQ (N-1, 9));
+
+  TEST_FUNC (f3, 2, N-1, 0, 0,
+    CHECK_RANGE_EQ(0, N-1, 2); CHECK_EQ (N-1, 0));
+
+  TEST_FUNC (f4, 0, N-1, 2, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f5, 2, N-1, -3, 6,
+    CHECK_RANGE_EQ (0, N-1, 8); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f6, 5, N-1, 0, 7,
+    CHECK_RANGE_EQ (0, N-1, 12); CHECK_EQ (N-1, 7));
+
+  /* Condition never met — full loop executes.  */
+  TEST_FUNC (f1, 0, -1, 0, 2,
+    CHECK_RANGE_EQ (0, N, 2));
+
+  TEST_FUNC (f2, -2, -1, 0, 5,
+    CHECK_RANGE_EQ (0, N, 3));
+
+  TEST_FUNC (f3, 1, -1, 0, 0,
+    CHECK_RANGE_EQ (0, N, 1));
+
+  TEST_FUNC (f4, 0, -1, 0, 7,
+    CHECK_RANGE_EQ (0, N, 7));
+
+  TEST_FUNC (f5, 1, -1, 0, 4,
+    CHECK_RANGE_EQ (0, N, 5));
+
+  TEST_FUNC (f6, 5, -1, 0, 3,
+    CHECK_RANGE_EQ (0, N, 8));
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_4.c b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_4.c
new file mode 100644
index 0000000000000000000000000000000000000000..68a5d0a09fdfd5664562e1bac3b5e586a37b3a6f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_4.c
@@ -0,0 +1,132 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fno-schedule-insns -fno-reorder-blocks -fno-schedule-insns2 --param aarch64-autovec-preference=asimd-only" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdio.h>
+
+#define N 640
+#ifndef TYPE
+#define TYPE float
+#endif
+#ifndef FMT
+#define FMT ".6f"
+#endif
+
+
+TYPE a[N] = {0};
+TYPE b[N] = {0};
+
+char *curr_test;
+
+/* Macro to define a function with a specific comparison */
+#define DEFINE_TEST_FUNC(NAME, OP)            \
+  __attribute__((noipa))		      \
+  void NAME(void) {                           \
+    for (int i = 0; i < N; i++) {             \
+      b[i] += a[i];                           \
+      if (a[i] OP 0)                          \
+        break;                                \
+    }                                         \
+  }
+
+/* Generate the six comparisons functions using the macro.  */
+DEFINE_TEST_FUNC(f1, >)
+DEFINE_TEST_FUNC(f2, >=)
+DEFINE_TEST_FUNC(f3, ==)
+DEFINE_TEST_FUNC(f4, !=)
+DEFINE_TEST_FUNC(f5, <)
+DEFINE_TEST_FUNC(f6, <=)
+
+__attribute__((noreturn))
+static inline void __abort_trace (const char *m, int i, TYPE result, TYPE expected)
+{
+   printf ("*** [%s] FAIL AT %s:%d in %s - expected %" FMT " but got %" FMT " at pos %d\n",
+           m, __FILE__, __LINE__, curr_test, expected, result, i);
+   __builtin_abort ();
+}
+
+/* Array setup macro.  */
+#define RESET_ARRAYS(_aval, _idx, _force, _bval)         \
+  do {                                                   \
+    _Pragma("GCC novector")				 \
+    for (int i = 0; i < N; ++i) {                        \
+      a[i] = _aval;                                      \
+      b[i] = _bval;                                      \
+    }                                                    \
+    if (_idx >= 0 && _idx < N)                           \
+      a[_idx] = _force;                                  \
+  } while (0)
+
+/* Value check macros.  */
+#define CHECK_EQ(_i, _val)                        \
+  do {                                            \
+    if (b[_i] != _val)                            \
+      __abort_trace ("single", _i, b[_i], _val);  \
+  } while (0)
+
+#define CHECK_RANGE_EQ(_start, _end, _val)               \
+  do {                                                   \
+    _Pragma("GCC novector")				 \
+    for (int i = _start; i < _end; ++i)                  \
+      if (b[i] != _val)                                  \
+        __abort_trace ("range", i, b[i], _val);          \
+  } while (0)
+
+#define str(s) #s
+#define TEST_FUNC(_func, _aval, _idx, _force, _bval, _check_stmt)  \
+  do {                                                             \
+    curr_test = str (_func);                                       \
+    RESET_ARRAYS((_aval), (_idx), (_force), (_bval));              \
+    _func();                                                       \
+    _check_stmt;                                                   \
+  } while (0)
+
+int main(void) {
+  /* Break on random intervals.  */
+  TEST_FUNC (f1, 1, 0, 1, 10, CHECK_EQ (0, 11); CHECK_EQ (1, 10));
+  TEST_FUNC (f2, -1, 5, 0, 10, CHECK_EQ (0, 9); CHECK_EQ (5, 10));
+  TEST_FUNC (f3, 3, 3, 0, 0, CHECK_EQ (0, 3); CHECK_EQ (3, 0));
+  TEST_FUNC (f4, 0, 4, 1, 1, CHECK_EQ (4, 2); CHECK_EQ (5, 1));
+  TEST_FUNC (f5, 1, 6, -1, 5, CHECK_EQ (6, 4); CHECK_EQ (7, 5));
+  TEST_FUNC (f6, 2, 10, 0, 7, CHECK_EQ (10, 7); CHECK_EQ (11, 7));
+
+  /* Break on last iteration.  */
+  TEST_FUNC (f1, 0, N-1, 1, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 2));
+
+  TEST_FUNC (f2, -5, N-1, 0, 9,
+    CHECK_RANGE_EQ (0, N-1, 4); CHECK_EQ (N-1, 9));
+
+  TEST_FUNC (f3, 2, N-1, 0, 0,
+    CHECK_RANGE_EQ(0, N-1, 2); CHECK_EQ (N-1, 0));
+
+  TEST_FUNC (f4, 0, N-1, 2, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f5, 2, N-1, -3, 6,
+    CHECK_RANGE_EQ (0, N-1, 8); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f6, 5, N-1, 0, 7,
+    CHECK_RANGE_EQ (0, N-1, 12); CHECK_EQ (N-1, 7));
+
+  /* Condition never met — full loop executes.  */
+  TEST_FUNC (f1, 0, -1, 0, 2,
+    CHECK_RANGE_EQ (0, N, 2));
+
+  TEST_FUNC (f2, -2, -1, 0, 5,
+    CHECK_RANGE_EQ (0, N, 3));
+
+  TEST_FUNC (f3, 1, -1, 0, 0,
+    CHECK_RANGE_EQ (0, N, 1));
+
+  TEST_FUNC (f4, 0, -1, 0, 7,
+    CHECK_RANGE_EQ (0, N, 7));
+
+  TEST_FUNC (f5, 1, -1, 0, 4,
+    CHECK_RANGE_EQ (0, N, 5));
+
+  TEST_FUNC (f6, 5, -1, 0, 3,
+    CHECK_RANGE_EQ (0, N, 8));
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_5.c b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_5.c
new file mode 100644
index 0000000000000000000000000000000000000000..52d95e9a71b7999376731e47a224936d4253ac2f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vect-early-break-cbranch_5.c
@@ -0,0 +1,132 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fno-schedule-insns -fno-reorder-blocks -fno-schedule-insns2 --param aarch64-autovec-preference=sve-only" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdio.h>
+
+#define N 640
+#ifndef TYPE
+#define TYPE float
+#endif
+#ifndef FMT
+#define FMT ".6f"
+#endif
+
+
+TYPE a[N] = {0};
+TYPE b[N] = {0};
+
+char *curr_test;
+
+/* Macro to define a function with a specific comparison */
+#define DEFINE_TEST_FUNC(NAME, OP)            \
+  __attribute__((noipa))		      \
+  void NAME(void) {                           \
+    for (int i = 0; i < N; i++) {             \
+      b[i] += a[i];                           \
+      if (a[i] OP 0)                          \
+        break;                                \
+    }                                         \
+  }
+
+/* Generate the six comparisons functions using the macro.  */
+DEFINE_TEST_FUNC(f1, >)
+DEFINE_TEST_FUNC(f2, >=)
+DEFINE_TEST_FUNC(f3, ==)
+DEFINE_TEST_FUNC(f4, !=)
+DEFINE_TEST_FUNC(f5, <)
+DEFINE_TEST_FUNC(f6, <=)
+
+__attribute__((noreturn))
+static inline void __abort_trace (const char *m, int i, TYPE result, TYPE expected)
+{
+   printf ("*** [%s] FAIL AT %s:%d in %s - expected %" FMT " but got %" FMT " at pos %d\n",
+           m, __FILE__, __LINE__, curr_test, expected, result, i);
+   __builtin_abort ();
+}
+
+/* Array setup macro.  */
+#define RESET_ARRAYS(_aval, _idx, _force, _bval)         \
+  do {                                                   \
+    _Pragma("GCC novector")				 \
+    for (int i = 0; i < N; ++i) {                        \
+      a[i] = _aval;                                      \
+      b[i] = _bval;                                      \
+    }                                                    \
+    if (_idx >= 0 && _idx < N)                           \
+      a[_idx] = _force;                                  \
+  } while (0)
+
+/* Value check macros.  */
+#define CHECK_EQ(_i, _val)                        \
+  do {                                            \
+    if (b[_i] != _val)                            \
+      __abort_trace ("single", _i, b[_i], _val);  \
+  } while (0)
+
+#define CHECK_RANGE_EQ(_start, _end, _val)               \
+  do {                                                   \
+    _Pragma("GCC novector")				 \
+    for (int i = _start; i < _end; ++i)                  \
+      if (b[i] != _val)                                  \
+        __abort_trace ("range", i, b[i], _val);          \
+  } while (0)
+
+#define str(s) #s
+#define TEST_FUNC(_func, _aval, _idx, _force, _bval, _check_stmt)  \
+  do {                                                             \
+    curr_test = str (_func);                                       \
+    RESET_ARRAYS((_aval), (_idx), (_force), (_bval));              \
+    _func();                                                       \
+    _check_stmt;                                                   \
+  } while (0)
+
+int main(void) {
+  /* Break on random intervals.  */
+  TEST_FUNC (f1, 1, 0, 1, 10, CHECK_EQ (0, 11); CHECK_EQ (1, 10));
+  TEST_FUNC (f2, -1, 5, 0, 10, CHECK_EQ (0, 9); CHECK_EQ (5, 10));
+  TEST_FUNC (f3, 3, 3, 0, 0, CHECK_EQ (0, 3); CHECK_EQ (3, 0));
+  TEST_FUNC (f4, 0, 4, 1, 1, CHECK_EQ (4, 2); CHECK_EQ (5, 1));
+  TEST_FUNC (f5, 1, 6, -1, 5, CHECK_EQ (6, 4); CHECK_EQ (7, 5));
+  TEST_FUNC (f6, 2, 10, 0, 7, CHECK_EQ (10, 7); CHECK_EQ (11, 7));
+
+  /* Break on last iteration.  */
+  TEST_FUNC (f1, 0, N-1, 1, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 2));
+
+  TEST_FUNC (f2, -5, N-1, 0, 9,
+    CHECK_RANGE_EQ (0, N-1, 4); CHECK_EQ (N-1, 9));
+
+  TEST_FUNC (f3, 2, N-1, 0, 0,
+    CHECK_RANGE_EQ(0, N-1, 2); CHECK_EQ (N-1, 0));
+
+  TEST_FUNC (f4, 0, N-1, 2, 1,
+    CHECK_RANGE_EQ (0, N-1, 1); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f5, 2, N-1, -3, 6,
+    CHECK_RANGE_EQ (0, N-1, 8); CHECK_EQ (N-1, 3));
+
+  TEST_FUNC (f6, 5, N-1, 0, 7,
+    CHECK_RANGE_EQ (0, N-1, 12); CHECK_EQ (N-1, 7));
+
+  /* Condition never met — full loop executes.  */
+  TEST_FUNC (f1, 0, -1, 0, 2,
+    CHECK_RANGE_EQ (0, N, 2));
+
+  TEST_FUNC (f2, -2, -1, 0, 5,
+    CHECK_RANGE_EQ (0, N, 3));
+
+  TEST_FUNC (f3, 1, -1, 0, 0,
+    CHECK_RANGE_EQ (0, N, 1));
+
+  TEST_FUNC (f4, 0, -1, 0, 7,
+    CHECK_RANGE_EQ (0, N, 7));
+
+  TEST_FUNC (f5, 1, -1, 0, 4,
+    CHECK_RANGE_EQ (0, N, 5));
+
+  TEST_FUNC (f6, 5, -1, 0, 3,
+    CHECK_RANGE_EQ (0, N, 8));
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_2.c b/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_2.c
new file mode 100644
index 0000000000000000000000000000000000000000..218349311d9044c0c0c195c72b0cc6ad43022448
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_2.c
@@ -0,0 +1,105 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-schedule-insns -fno-reorder-blocks -fno-schedule-insns2 --param aarch64-autovec-preference=asimd-only" } */
+/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */
+
+#pragma GCC target "+sve"
+
+#define N 640
+int a[N] = {0};
+int b[N] = {0};
+/*
+** f1:
+**	...
+**	cmpgt	p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0
+**	b.none	\.L[0-9]+
+**	...
+*/
+void f1 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] > 0)
+	break;
+    }
+}
+/*
+** f2:
+**	...
+**	cmpge	p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0
+**	b.none	\.L[0-9]+
+**	...
+*/
+void f2 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] >= 0)
+	break;
+    }
+}
+/*
+** f3:
+**	...
+**	cmpeq	p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0
+**	b.none	\.L[0-9]+
+**	...
+*/
+void f3 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] == 0)
+	break;
+    }
+}
+/*
+** f4:
+**	...
+**	cmpne	p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0
+**	b.none	\.L[0-9]+
+**	...
+*/
+void f4 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] != 0)
+	break;
+    }
+}
+/*
+** f5:
+**	...
+**	cmplt	p[0-9]+.s, p7/z, z[0-9]+.s, #0
+**	b.none	.L[0-9]+
+**	...
+*/
+void f5 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] < 0)
+	break;
+    }
+}
+/*
+** f6:
+**	...
+**	cmple	p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0
+**	b.none	\.L[0-9]+
+**	...
+*/
+void f6 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] <= 0)
+	break;
+    }
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_3.c b/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_3.c
new file mode 100644
index 0000000000000000000000000000000000000000..d4885b02c4a4c1338119c05bf812cfa521c3515b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/vect-early-break-cbranch_3.c
@@ -0,0 +1,112 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-schedule-insns -fno-reorder-blocks -fno-schedule-insns2 --param aarch64-autovec-preference=asimd-only" } */
+/* { dg-final { check-function-bodies "**" "" "" { target lp64 } } } */
+
+#pragma GCC target "+sve"
+
+#define N 640
+float a[N] = {0};
+float b[N] = {0};
+
+/*
+** f1:
+**	...
+**	fcmgt	p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0.0
+**	ptest	p[0-9]+, p[0-9]+\.b
+**	b.none	\.L[0-9]+
+**	...
+*/
+void f1 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] > 0)
+	break;
+    }
+}
+/*
+** f2:
+**	...
+**	fcmge	p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0.0
+**	ptest	p[0-9]+, p[0-9]+\.b
+**	b.none	\.L[0-9]+
+**	...
+*/
+void f2 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] >= 0)
+	break;
+    }
+}
+/*
+** f3:
+**	...
+**	fcmeq	p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0.0
+**	ptest	p[0-9]+, p[0-9]+\.b
+**	b.none	\.L[0-9]+
+**	...
+*/
+void f3 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] == 0)
+	break;
+    }
+}
+/*
+** f4:
+**	...
+**	fcmne	p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0.0
+**	ptest	p[0-9]+, p[0-9]+\.b
+**	b.none	\.L[0-9]+
+**	...
+*/
+void f4 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] != 0)
+	break;
+    }
+}
+/*
+** f5:
+**	...
+**	fcmlt	p[0-9]+.s, p7/z, z[0-9]+.s, #0.0
+**	ptest	p[0-9]+, p[0-9]+\.b
+**	b.none	.L[0-9]+
+**	...
+*/
+void f5 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] < 0)
+	break;
+    }
+}
+/*
+** f6:
+**	...
+**	fcmle	p[0-9]+.s, p[0-9]+/z, z[0-9]+.s, #0.0
+**	ptest	p[0-9]+, p[0-9]+\.b
+**	b.none	\.L[0-9]+
+**	...
+*/
+void f6 ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      b[i] += a[i];
+      if (a[i] <= 0)
+	break;
+    }
+}

Reply via email to