This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] ARM pre-indexing adress mode for absolute addresses (fwd)


Ping !

Got no answer since I posted this.


Nicolas

---------- Forwarded message ----------
Date: Mon, 15 Nov 2004 00:08:28 -0500 (EST)
From: Nicolas Pitre <nico@cam.org>
To: gcc-patches@gcc.gnu.org
Cc: Richard Earnshaw <rearnsha@arm.com>
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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]