Pengfei Li <pengfei....@arm.com> writes: > Hi, > > This patch backports the fix of r16-3083 to gcc-13. > > Compared to the trunk version, this is slightly different because those RTL > patterns in gcc-13 do not yet use the compact syntax for multiple > alternatives. > But this patch is functionally identical to the trunk fix. > > Bootstrapped and regtested on gcc-13. Ok for gcc-13 now?
OK, thanks. Richard > Thanks, > Pengfei > > -- >8 -- > > This patch fixes incorrect constraints in RTL patterns for AArch64 SVE > gather/scatter with type widening/narrowing and vector-plus-immediate > addressing. The bug leads to below "immediate offset out of range" > errors during assembly, eventually causing compilation failures. > > /tmp/ccsVqBp1.s: Assembler messages: > /tmp/ccsVqBp1.s:54: Error: immediate offset out of range 0 to 31 at operand 3 > -- `ld1b z1.d,p0/z,[z1.d,#64]' > > Current RTL patterns for such instructions incorrectly use vgw or vgd > constraints for the immediate operand, base on the vector element type > in Z registers (zN.s or zN.d). However, for gather/scatter with type > conversions, the immediate range for vector-plus-immediate addressing is > determined by the element type in memory, which differs from that in > vector registers. Using the wrong constraint can produce out-of-range > offset values that cannot be encoded in the instruction. > > This patch corrects the constraints used in these patterns. A test case > that reproduces the issue is also included. > > Bootstrapped and regression-tested on aarch64-linux-gnu. > > gcc/ChangeLog: > PR target/121449 > * config/aarch64/aarch64-sve.md > (mask_gather_load<mode><v_int_container>): Use vg<Vesize> > constraints for alternatives with immediate offset. > (mask_scatter_store<mode><v_int_container>): Likewise. > > gcc/testsuite/ChangeLog: > PR target/121449 > * g++.target/aarch64/sve/pr121449.C: New test. > --- > gcc/config/aarch64/aarch64-sve.md | 8 ++-- > .../g++.target/aarch64/sve/pr121449.C | 44 +++++++++++++++++++ > 2 files changed, 48 insertions(+), 4 deletions(-) > create mode 100644 gcc/testsuite/g++.target/aarch64/sve/pr121449.C > > diff --git a/gcc/config/aarch64/aarch64-sve.md > b/gcc/config/aarch64/aarch64-sve.md > index 9cb09187c62..89f4e6d3b75 100644 > --- a/gcc/config/aarch64/aarch64-sve.md > +++ b/gcc/config/aarch64/aarch64-sve.md > @@ -1421,7 +1421,7 @@ > [(set (match_operand:SVE_4 0 "register_operand" "=w, w, w, w, w, w") > (unspec:SVE_4 > [(match_operand:VNx4BI 5 "register_operand" "Upl, Upl, Upl, Upl, Upl, > Upl") > - (match_operand:DI 1 "aarch64_sve_gather_offset_<Vesize>" "Z, vgw, > rk, rk, rk, rk") > + (match_operand:DI 1 "aarch64_sve_gather_offset_<Vesize>" "Z, > vg<Vesize>, rk, rk, rk, rk") > (match_operand:VNx4SI 2 "register_operand" "w, w, w, w, w, w") > (match_operand:DI 3 "const_int_operand" "Ui1, Ui1, Z, Ui1, Z, Ui1") > (match_operand:DI 4 "aarch64_gather_scale_operand_<Vesize>" "Ui1, > Ui1, Ui1, Ui1, i, i") > @@ -1443,7 +1443,7 @@ > [(set (match_operand:SVE_2 0 "register_operand" "=w, w, w, w") > (unspec:SVE_2 > [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl, Upl, Upl") > - (match_operand:DI 1 "aarch64_sve_gather_offset_<Vesize>" "Z, vgd, > rk, rk") > + (match_operand:DI 1 "aarch64_sve_gather_offset_<Vesize>" "Z, > vg<Vesize>, rk, rk") > (match_operand:VNx2DI 2 "register_operand" "w, w, w, w") > (match_operand:DI 3 "const_int_operand") > (match_operand:DI 4 "aarch64_gather_scale_operand_<Vesize>" "Ui1, > Ui1, Ui1, i") > @@ -2254,7 +2254,7 @@ > [(set (mem:BLK (scratch)) > (unspec:BLK > [(match_operand:VNx4BI 5 "register_operand" "Upl, Upl, Upl, Upl, Upl, > Upl") > - (match_operand:DI 0 "aarch64_sve_gather_offset_<Vesize>" "Z, vgw, > rk, rk, rk, rk") > + (match_operand:DI 0 "aarch64_sve_gather_offset_<Vesize>" "Z, > vg<Vesize>, rk, rk, rk, rk") > (match_operand:VNx4SI 1 "register_operand" "w, w, w, w, w, w") > (match_operand:DI 2 "const_int_operand" "Ui1, Ui1, Z, Ui1, Z, Ui1") > (match_operand:DI 3 "aarch64_gather_scale_operand_<Vesize>" "Ui1, > Ui1, Ui1, Ui1, i, i") > @@ -2276,7 +2276,7 @@ > [(set (mem:BLK (scratch)) > (unspec:BLK > [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl, Upl, Upl") > - (match_operand:DI 0 "aarch64_sve_gather_offset_<Vesize>" "Z, vgd, > rk, rk") > + (match_operand:DI 0 "aarch64_sve_gather_offset_<Vesize>" "Z, > vg<Vesize>, rk, rk") > (match_operand:VNx2DI 1 "register_operand" "w, w, w, w") > (match_operand:DI 2 "const_int_operand") > (match_operand:DI 3 "aarch64_gather_scale_operand_<Vesize>" "Ui1, > Ui1, Ui1, i") > diff --git a/gcc/testsuite/g++.target/aarch64/sve/pr121449.C > b/gcc/testsuite/g++.target/aarch64/sve/pr121449.C > new file mode 100644 > index 00000000000..b2e13765dfa > --- /dev/null > +++ b/gcc/testsuite/g++.target/aarch64/sve/pr121449.C > @@ -0,0 +1,44 @@ > +/* PR target/121449 */ > +/* { dg-do assemble { target aarch64_asm_sve_ok } } */ > +/* { dg-options "-O3 -save-temps" } */ > + > +struct example; > + > +struct array { > + unsigned length(); > + example *operator[](unsigned i) { > + example **data = reinterpret_cast<example **>(this); > + return data[i]; > + } > +}; > + > +struct example { > + int a[16]; > + bool is_even; > + int version; > + int count() { return is_even ? 2 : 1; } > + void fun1(int, long); > + void fun2(unsigned, unsigned); > + void process(array &, array &); > +}; > + > +bool found; > + > +void example::process(array &a, array &b) { > + for (unsigned i = 1; a.length(); i++) { > + long total = 0; > + for (unsigned k = 0; k <= i; k++) { > + total += a[k]->count(); > + } > + for (unsigned j = 0; j < i; j++) { > + int major = b[j]->version; > + if (found) > + major += i; > + fun1(i + 1, total); > + fun2(j, major); > + } > + } > +} > + > +/* { dg-final { scan-assembler-not {\tld1b\t(z[0-9]+)\.d, p[0-7]/z, > \[(z[0-9]+)\.d, #64\]} } } */ > +