This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
ARM pre-indexing adress mode for absolute addresses
- From: Nicolas Pitre <nico at cam dot org>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Richard Earnshaw <rearnsha at arm dot com>
- Date: Mon, 15 Nov 2004 00:08:28 -0500 (EST)
- Subject: ARM pre-indexing adress mode for absolute addresses
Last year or so I tried to fix awful assembly generation for code like
this:
#define FOO ((volatile int *)0xf8000124)
#define BAR ((volatile int *)0xf8000458)
#define BAZ ((volatile int *)0xf800078c)
int test() { return *FOO + *BAR + *BAZ; }
Using multiple different yet closely related absolute addresses is quite
common for hardware driver programming. Unfortunately gcc has a
tendency to not take advantage of the preindexed addressing mode in that
case, generating a new wide constant to be loaded into a register
instead. Things are even worse when that constant is located in the
minipool making the resulting binary even larger and often slower.
Playing with the value of arm_constant_limit wasn't a proper solution to
this since arm_split_constant() just doesn't know if they're memory
addresses or not. When they're not it usually produce larger code for
no gain.
This time I tried to find a way to selectively split constants but only
when they're actual addresses, and arm_legitimize_address() appeared to
be the perfect place for that kind of processing. I'm therefore asking
permission to commit the following patch:
[date] Nicolas Pitre <nico@cam.org>
* config/arm/arm.c (arm_legitimize_address): Split absolute addresses
to alow matching pre-indexed addressing mode.
(arm_override_options): Remove now irrelevant comment.
Index: gcc/config/arm/arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.418
diff -u -r1.418 arm.c
--- gcc/config/arm/arm.c 11 Nov 2004 14:52:54 -0000 1.418
+++ gcc/config/arm/arm.c 14 Nov 2004 21:58:13 -0000
@@ -1143,10 +1143,6 @@
if (optimize_size)
{
- /* There's some dispute as to whether this should be 1 or 2. However,
- experiments seem to show that in pathological cases a setting of
- 1 degrades less severely than a setting of 2. This could change if
- other parts of the compiler change their behavior. */
arm_constant_limit = 1;
/* If optimizing for size, bump the number of instructions that we
@@ -3541,6 +3537,25 @@
x = gen_rtx_MINUS (SImode, xop0, xop1);
}
+ /* Make sure to take full advantage of the pre-indexed addressing mode
+ with absolute addresses which often allows for the base register to
+ be factorized for multiple adjacent memory references, and it might
+ even allows for the mini pool to be avoided entirely. */
+ else if (GET_CODE (x) == CONST_INT)
+ {
+ HOST_WIDE_INT mask, base, index;
+ rtx base_reg;
+
+ /* ldr and ldrb can use a 12 bit index, ldrsb and the rest can only
+ use a 8 bit index. So let's use a 12 bit index only for SImode and
+ hope that arm_gen_constant will enable ldrb to use more bits. */
+ mask = (mode == SImode) ? 0xfff : 0xff;
+ base = INTVAL (x) & ~mask;
+ index = INTVAL (x) & mask;
+ base_reg = force_reg (SImode, GEN_INT (base));
+ x = gen_rtx_PLUS (SImode, base_reg, GEN_INT (index));
+ }
+
if (flag_pic)
{
/* We need to find and carefully transform any SYMBOL and LABEL