This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, ivopt] Try aligned offset when get_address_cost
- From: "Zhenqiang Chen" <zhenqiang dot chen at arm dot com>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 4 Aug 2014 14:28:53 +0800
- Subject: [PATCH, ivopt] Try aligned offset when get_address_cost
- Authentication-results: sourceware.org; auth=none
Hi,
For some TARGET, like ARM THUMB1, the offset in load/store should be nature
aligned. But in function get_address_cost, when computing max_offset, it
only tries byte-aligned offsets:
((unsigned HOST_WIDE_INT) 1 << i) - 1
which can not meet thumb_legitimate_offset_p check called from
thumb1_legitimate_address_p for HImode and SImode.
The patch adds additional try for aligned offset:
((unsigned HOST_WIDE_INT) 1 << i) - GET_MODE_SIZE (address_mode).
Bootstrap and no make check regression on X86-64.
No make check regression on qemu for Cortex-m0 and Cortex-m3.
For Cortex-m0, no performance changes with coremark and dhrystone. Coremark
code size is ~0.44 smaller. And eembcv2 code size is ~0.22 smaller. CSiBE
code size is ~0.05% smaller.
OK for trunk?
Thanks!
-Zhenqiang
ChangeLog
2014-08-04 Zhenqiang Chen <zhenqiang.chen@arm.com>
* tree-ssa-loop-ivopts.c (get_address_cost): Try aligned offset.
testsuite/ChangeLog:
2014-08-04 Zhenqiang Chen <zhenqiang.chen@arm.com>
* gcc.target/arm/get_address_cost_aligned_max_offset.c: New test.
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 3b4a6cd..562122a 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -3308,6 +3308,18 @@ get_address_cost (bool symbol_present, bool
var_present,
XEXP (addr, 1) = gen_int_mode (off, address_mode);
if (memory_address_addr_space_p (mem_mode, addr, as))
break;
+ /* For some TARGET, like ARM THUMB1, the offset should be nature
+ aligned. Try an aligned offset if address_mode is not QImode.
*/
+ off = (address_mode == QImode)
+ ? 0
+ : ((unsigned HOST_WIDE_INT) 1 << i)
+ - GET_MODE_SIZE (address_mode);
+ if (off > 0)
+ {
+ XEXP (addr, 1) = gen_int_mode (off, address_mode);
+ if (memory_address_addr_space_p (mem_mode, addr, as))
+ break;
+ }
}
if (i == -1)
off = 0;
diff --git
a/gcc/testsuite/gcc.target/arm/get_address_cost_aligned_max_offset.c
b/gcc/testsuite/gcc.target/arm/get_address_cost_aligned_max_offset.c
new file mode 100644
index 0000000..cc3e2f7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/get_address_cost_aligned_max_offset.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-mthumb -O2" } */
+/* { dg-require-effective-target arm_thumb1_ok } */
+
+unsigned int
+test (const short p16[6 * 64])
+{
+ unsigned int i = 6;
+ unsigned int ret = 0;
+
+ do
+ {
+ unsigned long long *p64 = (unsigned long long*) p16;
+ unsigned int *p32 = (unsigned int*) p16;
+ ret += ret;
+ if (p16[1] || p32[1])
+ ret++;
+ else if (p64[1] | p64[2] | p64[3])
+ ret++;
+ p16 += 64;
+ i--;
+ } while (i != 0);
+
+ return ret;
+}
+
+/* { dg-final { scan-assembler-not "#22" } } */
+/* { dg-final { scan-assembler-not "#14" } } */