On Thu, Jul 20, 2017 at 5:49 AM, Wilco Dijkstra <wilco.dijks...@arm.com> wrote: > In https://gcc.gnu.org/ml/gcc-patches/2017-06/msg01125.html Jiong > pointed out some addressing inefficiencies due to a recent change in > regcprop (https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00775.html). > > This patch improves aarch64_legitimize_address_displacement to split > unaligned offsets of TImode and TFmode accesses. The resulting code > is better and no longer relies on the original regcprop optimization. > > For the test we now produce: > > add x1, sp, 4 > stp xzr, xzr, [x1, 24] > > rather than: > > mov x1, sp > add x1, x1, 28 > stp xzr, xzr, [x1] > > OK for commit?
Note this patch will semi-conflict with my patch to support DFP (https://gcc.gnu.org/ml/gcc-patches/2017-07/msg00788.html). I don't mind updating that patch if this patch gets approved but just letting you know about that conflict. Thanks, Andrew > > ChangeLog: > 2017-06-20 Wilco Dijkstra <wdijk...@arm.com> > > * config/aarch64/aarch64.c (aarch64_legitimize_address_displacement): > Improve unaligned TImode/TFmode base/offset split. > > testsuite > * gcc.target/aarch64/ldp_stp_unaligned_2.c: New file. > > -- > diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c > index > 90f248025a4fa928ebac657b689010f74dd100b5..208fdbe7262a93ee8caada2868a8d447de619c6e > 100644 > --- a/gcc/config/aarch64/aarch64.c > +++ b/gcc/config/aarch64/aarch64.c > @@ -4705,15 +4705,17 @@ aarch64_legitimate_address_p (machine_mode mode, rtx > x, > /* Split an out-of-range address displacement into a base and offset. > Use 4KB range for 1- and 2-byte accesses and a 16KB range otherwise > to increase opportunities for sharing the base address of different sizes. > - For unaligned accesses and TI/TF mode use the signed 9-bit range. */ > + Unaligned accesses use the signed 9-bit range, TImode/TFmode use > + the intersection of signed scaled 7-bit and signed 9-bit offset. */ > static bool > aarch64_legitimize_address_displacement (rtx *disp, rtx *off, machine_mode > mode) > { > HOST_WIDE_INT offset = INTVAL (*disp); > HOST_WIDE_INT base = offset & ~(GET_MODE_SIZE (mode) < 4 ? 0xfff : 0x3ffc); > > - if (mode == TImode || mode == TFmode > - || (offset & (GET_MODE_SIZE (mode) - 1)) != 0) > + if (mode == TImode || mode == TFmode) > + base = (offset + 0x100) & ~0x1f8; > + else if ((offset & (GET_MODE_SIZE (mode) - 1)) != 0) > base = (offset + 0x100) & ~0x1ff; > > *off = GEN_INT (base); > diff --git a/gcc/testsuite/gcc.target/aarch64/ldp_stp_unaligned_2.c > b/gcc/testsuite/gcc.target/aarch64/ldp_stp_unaligned_2.c > new file mode 100644 > index > 0000000000000000000000000000000000000000..1e46755a39a0b97fa7af704086f82ffd5a216fb4 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/ldp_stp_unaligned_2.c > @@ -0,0 +1,18 @@ > +/* { dg-options "-O2 -fomit-frame-pointer" } */ > + > +/* Check that we split unaligned LDP/STP into base and aligned offset. */ > + > +typedef struct > +{ > + int a, b, c, d, e; > +} S; > + > +void foo (S *); > + > +void test (int x) > +{ > + S s = { .a = x }; > + foo (&s); > +} > + > +/* { dg-final { scan-assembler-not "mov\tx\[0-9\]+, sp" } } */