The following testcase

const double a[] = {0, 1, 2, 3, 4, 5};
__attribute__((noipa))
int f(double x)
{
    int i = 0;
#pragma GCC unroll 0
    while (i < 6 && a[i] <= x)
        ++i;
    return i;
}
int main(void)
{
    int result = f(2.0);
    return result != 3;
}

when compiled with -O3 -fno-trapping-math -march=armv8-a+sve

generates incorrect code:

f:
        ptrue   p15.b, vl16
        ptrue   p7.b, all
        dup     v30.2d, v0.d[0]
        adrp    x2, .LANCHOR0
        add     x1, x2, :lo12:.LANCHOR0
        mov     w0, 0
.L5:
        ldr     q31, [x1]
        add     x1, x1, 16
        fcmle   p14.d, p7/z, z31.d, z30.d
        bics    p14.b, p15/z, p7.b, p14.b
        b.any   .L10
        add     w0, w0, 2
        cmp     w0, 6
        bne     .L5
        ret

with this patch the mask is corrected to

f:
        ptrue   p15.d, vl2
        ptrue   p7.b, all
        dup     v30.2d, v0.d[0]
        adrp    x2, .LANCHOR0
        add     x1, x2, :lo12:.LANCHOR0
        mov     w0, 0
.L5:
        ldr     q31, [x1]
        add     x1, x1, 16
        fcmle   p14.d, p7/z, z31.d, z30.d
        bics    p14.b, p15/z, p7.b, p14.b
        b.any   .L10
        add     w0, w0, 2
        cmp     w0, 6
        bne     .L5
        ret

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

Ok for master? and GCC-16?

Thanks,
Tamar

gcc/ChangeLog:

        PR target/128665
        * config/aarch64/aarch64-simd.md (vec_cbranch_any,
        vec_cbranch_all): Correct mask.

gcc/testsuite/ChangeLog:

        PR target/128665
        * gcc.target/aarch64/sve/vect-revectorize-ptest-1.c: New test.

---

-- 
diff --git a/gcc/config/aarch64/aarch64-simd.md 
b/gcc/config/aarch64/aarch64-simd.md
index 
11705bc9073801dbc1a25ce3d9723ba9a96c446f..9c054090defab1b461f684eb4ddf234f1e40fe21
 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -4585,6 +4585,16 @@ (define_expand "<optab><mode>"
        = exact_div (GET_MODE_BITSIZE (<MODE>mode), 8).to_constant ();
       machine_mode pred_mode = aarch64_sve_pred_mode (full_mode);
       rtx ptrue = aarch64_ptrue_reg (VNx16BImode, lanes);
+      /* The predicate created above limits the VL but does not encapsulate
+        the element width from the original mode.  However the interface to
+        aarch64_ptrue_reg doesn't allow this so we have to create 1 predicate
+        for the length and one for the shape, and AND them together.  Constant
+        folding takes care of the rest.  This is easier than manually encoding
+        the bits.  */
+      rtx mask
+       = force_reg (VNx16BImode,
+                    aarch64_ptrue_all (GET_MODE_UNIT_SIZE (<MODE>mode)));
+      emit_insn (gen_and3 (VNx16BImode, ptrue, ptrue, mask));
       rtx hint = gen_int_mode (SVE_MAYBE_NOT_PTRUE, SImode);
 
       rtx tmp = gen_reg_rtx (pred_mode);
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vect-revectorize-ptest-1.c 
b/gcc/testsuite/gcc.target/aarch64/sve/vect-revectorize-ptest-1.c
new file mode 100644
index 
0000000000000000000000000000000000000000..777e4d3fc00aec45e1f6019476853f367adcba03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vect-revectorize-ptest-1.c
@@ -0,0 +1,23 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fno-trapping-math -march=armv8-a+sve" } */
+
+/* PTEST must ignore the predicate bits between 64-bit elements.  */
+
+const double a[] = { 0, 1, 2, 3, 4, 5 };
+
+__attribute__((noipa))
+int
+f (double x)
+{
+  int i = 0;
+#pragma GCC unroll 0
+  while (i < 6 && a[i] <= x)
+    ++i;
+  return i;
+}
+
+int
+main (void)
+{
+  return f (2.0) != 3;
+}

Reply via email to