From: Kyrylo Tkachov <[email protected]>
combine_simplify_rtx runs make_compound_operation over the address of a MEM
so that the shifts and masks combine has introduced are turned back into the
forms the target's address predicates recognize. A PREFETCH holds an address
too, and aarch64 classifies it with the same routine it uses for a MEM, but
that address never gets the treatment, so a zero extend that combine has
rewritten as an AND with 0xffffffff is never rewritten back:
Failed to match this instruction:
(prefetch (plus:DI (and:DI (subreg:DI (reg:SI 108 [ i ]) 0)
(const_int 4294967295 [0xffffffff]))
(reg/f:DI 107 [ b ]))
(const_int 0 [0])
(const_int 3 [0x3]))
On aarch64 the result is that __builtin_prefetch (b + i, 0, 3) with a 32-bit
i needs a separate address computation while a load of b[i] at the same
address does not:
before after
add x1, x0, w1, uxtw prfm PLDL1KEEP, [x0, w1, uxtw]
prfm PLDL1KEEP, [x1]
Handle PREFETCH alongside MEM.
zstd 1.5.7 prefetches its match candidate through a 32-bit index in
ZSTD_RowFindBestMatch, which is 85% of the work at compression level 9.
Compressing the Silesia corpus on Grace with -mcpu=grace -O3, this saves
~1.65% dynamic instructions.
Bootstrapped and tested on aarch64-none-linux-gnu and x86_64-linux.
Ok for trunk?
Thanks,
Kyrill
gcc/ChangeLog:
* combine.cc (combine_simplify_rtx): Handle PREFETCH like MEM when
simplifying the address.
gcc/testsuite/ChangeLog:
* gcc.target/aarch64/prefetch-extend-1.c: New test.
Signed-off-by: Kyrylo Tkachov <[email protected]>
---
gcc/combine.cc | 4 ++++
.../gcc.target/aarch64/prefetch-extend-1.c | 20 +++++++++++++++++++
2 files changed, 24 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/aarch64/prefetch-extend-1.c
diff --git a/gcc/combine.cc b/gcc/combine.cc
index 743026317ce..35c6a529950 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -5954,6 +5954,10 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, bool
in_dest, bool in_cond)
/* A little bit of algebraic simplification here. */
switch (code)
{
+ case PREFETCH:
+ /* A prefetch reaches memory through an address, and targets recognize
+ that address with the same predicates they use for a MEM, so it
+ needs the same treatment. */
case MEM:
/* Ensure that our address has any ASHIFTs converted to MULT in case
address-recognizing predicates are called later. */
diff --git a/gcc/testsuite/gcc.target/aarch64/prefetch-extend-1.c
b/gcc/testsuite/gcc.target/aarch64/prefetch-extend-1.c
new file mode 100644
index 00000000000..0037dfd43c3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/prefetch-extend-1.c
@@ -0,0 +1,20 @@
+/* A prefetch reaches memory through an address that PRFM can hold in an
+ extended-register form, just like a load of the same address does. */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void
+pf_uxtw (const unsigned char *b, unsigned int i)
+{
+ __builtin_prefetch (b + i, 0, 3);
+}
+
+void
+pf_sxtw (const unsigned char *b, int i)
+{
+ __builtin_prefetch (b + i, 0, 3);
+}
+
+/* { dg-final { scan-assembler-times {prfm\tPLDL1KEEP, \[x[0-9]+, w[0-9]+,
uxtw\]} 1 } } */
+/* { dg-final { scan-assembler-times {prfm\tPLDL1KEEP, \[x[0-9]+, w[0-9]+,
sxtw\]} 1 } } */
+/* { dg-final { scan-assembler-not {add\tx[0-9]+, x[0-9]+, w[0-9]+, [us]xtw\n}
} } */
--
2.50.1 (Apple Git-155)