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;
+}