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]

[RFC,arm] Pass insn to LEGITIMIZE_RELOAD_ADDRESS


On arm CPUs we have different addressing modes for coprocessor and core 
load/store insns. The result is that the range of valid offsets depends on 
the class of the data register being loaded/stored.

In most cases this is accommodated by an extra memory constaint in the insn 
pattern. However in LEGITIMIZE_RELOAD_ADDRESS all we know is the mode of mem. 
Ideally we want to know which insn/alternative we're reloading for.

The patch below passes the insn being reloaded to L_R_A, and uses the greater 
reload range if the insn involves core data registers.

I looks like all the required information is available, however I don't 
understand enough to tell if it's safe to use it.

Is this going to break because of some other bit of the compiler I don't know 
about? Is there a better way of doing this?

N.B. The existing code is incorrect, and can generate invalid instructions. 
The conservative solution is to always assume the smaller offset range.

Tested with cross to arm-none-elf.
Ok?

Paul

2004-06-19  Paul Brook  <paul@codesourcery.com>

	* config/alpha/alpha.h (LEGITIMIZE_RELOAD_ADDRESS): Add extra
	parameter.
	* config/avr/avr.h (LEGITIMIZE_RELOAD_ADDRESS): Ditto.
	* config/c4x/c4x.h (LEGITIMIZE_RELOAD_ADDRESS): Ditto.
	* config/cris/cris.h (LEGITIMIZE_RELOAD_ADDRESS): Ditto.
	* config/ip2k/ip2k.h (LEGITIMIZE_RELOAD_ADDRESS): Ditto.
	* config/m68hc11/m68hc11.h (LEGITIMIZE_RELOAD_ADDRESS): Ditto.
	* config/pa/pa.h (LEGITIMIZE_RELOAD_ADDRESS): Ditto.
	* config/rs6000/rs6000.h (LEGITIMIZE_RELOAD_ADDRESS): Ditto.
	* config/sh/sh.h (LEGITIMIZE_RELOAD_ADDRESS): Ditto.
	* config/sparc/sparc.h (LEGITIMIZE_RELOAD_ADDRESS): Ditto.
	* config/arm/arm.h (LEGITIMIZE_RELOAD_ADDRESS): Ditto.
	(ARM_LEGITIMIZE_RELOAD_ADDRESS): Only use large offsets for arm insns.
	* doc/tm.texi (ARM_LEGITIMIZE_RELOAD_ADDRESS): Add extra parameter.
	* reload.c (find_reloads_address): Pass insn to target hook.

Index: reload.c
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/reload.c,v
retrieving revision 1.244
diff -u -p -r1.244 reload.c
--- reload.c	15 Jun 2004 18:02:33 -0000	1.244
+++ reload.c	19 Jun 2004 15:35:01 -0000
@@ -4768,7 +4768,7 @@ find_reloads_address (enum machine_mode 
       if (memrefloc)
 	{
 	  LEGITIMIZE_RELOAD_ADDRESS (ad, GET_MODE (*memrefloc), opnum, type,
-				     ind_levels, win);
+				     ind_levels, insn, win);
 	}
       break;
     win:
Index: config/alpha/alpha.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/alpha/alpha.h,v
retrieving revision 1.220
diff -u -p -r1.220 alpha.h
--- config/alpha/alpha.h	11 Jun 2004 18:41:42 -0000	1.220
+++ config/alpha/alpha.h	19 Jun 2004 16:24:25 -0000
@@ -1306,7 +1306,7 @@ do {								\
    operand.  If we find one, push the reload and jump to WIN.  This
    macro is used in only one place: `find_reloads_address' in reload.c.  */
    
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,WIN)		     \
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,I,WIN)	     \
 do {									     \
   rtx new_x = alpha_legitimize_reload_address (X, MODE, OPNUM, TYPE, IND_L); 
\
   if (new_x)								     \
Index: config/arm/arm.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.237
diff -u -p -r1.237 arm.h
--- config/arm/arm.h	21 May 2004 01:03:16 -0000	1.237
+++ config/arm/arm.h	19 Jun 2004 16:55:06 -0000
@@ -1370,7 +1370,7 @@ enum reg_class
    For the ARM, we wish to handle large displacements off a base
    register by splitting the addend across a MOV and the mem insn.
    This can cut the number of reloads needed.  */
-#define ARM_LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND, WIN)	   \
+#define ARM_LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND, I, WIN)   \
   do									   \
     {									   \
       if (GET_CODE (X) == PLUS						   \
@@ -1382,15 +1382,44 @@ enum reg_class
 	  HOST_WIDE_INT val = INTVAL (XEXP (X, 1));			   \
 	  HOST_WIDE_INT low, high;					   \
 									   \
-	  if (MODE == DImode || (TARGET_SOFT_FLOAT && TARGET_FPA	   \
-		                 && MODE == DFmode))			   \
+	  if (MODE == DImode || (MODE == DFmode && TARGET_SOFT_FLOAT))	   \
 	    low = ((val & 0xf) ^ 0x8) - 0x8;				   \
 	  else if (TARGET_MAVERICK && TARGET_HARD_FLOAT)		   \
 	    /* Need to be careful, -256 is not a valid offset.  */	   \
 	    low = val >= 0 ? (val & 0xff) : -((-val) & 0xff);		   \
-	  else if (MODE == SImode					   \
-		   || (MODE == SFmode && TARGET_SOFT_FLOAT && TARGET_FPA)  \
-		   || ((MODE == HImode || MODE == QImode) && ! arm_arch4)) \
+	  else if (mode == SImode					   \
+		   || (mode == SFmode && (TARGET_SOFT_FLOAT || TARGET_VFP))) \
+	    {								   \
+	      rtx op = NULL_RTX;					   \
+	      if (I && !TARGET_SOFT_FLOAT)				   \
+		{							   \
+		  /* We have different restrictions for coprocessor	   \
+		     instructions.  Identify these by the type of data	   \
+		     register used.  */					   \
+		  op = single_set (I);					   \
+		  if (op)						   \
+		    {							   \
+		      if (GET_CODE (XEXP (op, 0)) == REG)		   \
+			op = XEXP (op, 0);				   \
+		      else if (GET_CODE (XEXP (op, 0)) == SUBREG	   \
+			       && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG) \
+			op = XEXP (XEXP (op, 0), 0);			   \
+		      else if (GET_CODE (XEXP (op, 1)) == REG)		   \
+			op = XEXP (op, 1);				   \
+		      else if (GET_CODE (XEXP (op, 1)) == SUBREG	   \
+			       && GET_CODE (XEXP (XEXP (op, 1), 0)) == REG) \
+			op = XEXP (XEXP (op, 1), 0);			   \
+		      else						   \
+			op = NULL_RTX;					   \
+		    }							   \
+		}							   \
+	      if (TARGET_SOFT_FLOAT					   \
+		  || (op && REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS)) \
+		low = val >= 0 ? (val & 0xfff) : -((-val) & 0xfff);	   \
+	      else							   \
+		low = val >= 0 ? (val & 0x3ff) : -((-val) & 0x3ff);	   \
+	    }								   \
+	  else if ((mode == HImode || mode == QImode) && ! arm_arch4)	   \
 	    /* Need to be careful, -4096 is not a valid offset.  */	   \
 	    low = val >= 0 ? (val & 0xfff) : -((-val) & 0xfff);		   \
 	  else if ((MODE == HImode || MODE == QImode) && arm_arch4)	   \
@@ -1450,9 +1479,9 @@ enum reg_class
     }									\
 }
 
-#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN)   \
+#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, I, WIN) \
   if (TARGET_ARM)							   \
-    ARM_LEGITIMIZE_RELOAD_ADDRESS (X, MODE, OPNUM, TYPE, IND_LEVELS, WIN); \
+    ARM_LEGITIMIZE_RELOAD_ADDRESS (X, MODE, OPNUM, TYPE, IND_LEVELS, I, WIN);
\
   else									   \
     THUMB_LEGITIMIZE_RELOAD_ADDRESS (X, MODE, OPNUM, TYPE, IND_LEVELS, WIN)
   
Index: config/avr/avr.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/avr/avr.h,v
retrieving revision 1.105
diff -u -p -r1.105 avr.h
--- config/avr/avr.h	25 May 2004 09:48:47 -0000	1.105
+++ config/avr/avr.h	19 Jun 2004 16:25:11 -0000
@@ -444,7 +444,7 @@ extern int avr_reg_order[];
 }
 
 #define XEXP_(X,Y) (X)
-#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN)    \
+#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, I, WIN) \
 do {									    \
   if (1&&(GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC))	    \
     {									    \
Index: config/c4x/c4x.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/c4x/c4x.h,v
retrieving revision 1.144
diff -u -p -r1.144 c4x.h
--- config/c4x/c4x.h	21 May 2004 13:16:34 -0000	1.144
+++ config/c4x/c4x.h	19 Jun 2004 16:25:29 -0000
@@ -1293,7 +1293,7 @@ CUMULATIVE_ARGS;
   }									\
 }
 
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN)     \
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,I,WIN)   \
 {									\
   if (MODE != HImode							\
       && MODE != HFmode							\
Index: config/cris/cris.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/cris/cris.h,v
retrieving revision 1.73
diff -u -p -r1.73 cris.h
--- config/cris/cris.h	1 May 2004 16:27:45 -0000	1.73
+++ config/cris/cris.h	19 Jun 2004 16:26:30 -0000
@@ -1258,7 +1258,7 @@ struct cum_args {int regs;};
     When the right thing happens in reload, the kludge can
    be removed; still not as of 2003-02-27.  */
 
-#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN) \
+#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, I, WIN) \
   do									\
     {									\
       if (GET_CODE (X) == PLUS						\
Index: config/ip2k/ip2k.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/ip2k/ip2k.h,v
retrieving revision 1.40
diff -u -p -r1.40 ip2k.h
--- config/ip2k/ip2k.h	21 May 2004 01:03:18 -0000	1.40
+++ config/ip2k/ip2k.h	19 Jun 2004 16:27:16 -0000
@@ -546,7 +546,7 @@ do {									\
    base pointer since IP only directly supports a zero displacement.
    (Note that we have modified all the HI patterns to correctly handle
    IP references by manipulating iph:ipl as we fetch the pieces).  */
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND,WIN)		     \
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND,I,WIN)		     \
 {									     \
   if (GET_CODE (X) == PLUS						     \
       && REG_P (XEXP (X, 0))						     \
Index: config/m68hc11/m68hc11.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/m68hc11/m68hc11.h,v
retrieving revision 1.87
diff -u -p -r1.87 m68hc11.h
--- config/m68hc11/m68hc11.h	6 Jun 2004 13:56:33 -0000	1.87
+++ config/m68hc11/m68hc11.h	19 Jun 2004 16:27:24 -0000
@@ -1413,7 +1413,7 @@ extern unsigned char m68hc11_reg_valid_f
    For M68HC12, the 64K offset range is available.
    */
 
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN)     \
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,I,WIN)     \
 do {                                                                    \
   /* We must recognize output that we have already generated ourselves.  */ \
   if (GET_CODE (X) == PLUS						\
Index: config/pa/pa.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/pa/pa.h,v
retrieving revision 1.218
diff -u -p -r1.218 pa.h
--- config/pa/pa.h	13 May 2004 06:40:03 -0000	1.218
+++ config/pa/pa.h	19 Jun 2004 16:27:35 -0000
@@ -1562,7 +1562,7 @@ extern int may_call_alloca;
    can be reused.
 
    There may be more opportunities to improve code with this hook.  */
-#define LEGITIMIZE_RELOAD_ADDRESS(AD, MODE, OPNUM, TYPE, IND, WIN) 	\
+#define LEGITIMIZE_RELOAD_ADDRESS(AD, MODE, OPNUM, TYPE, IND, I, WIN) 	\
 do { 									\
   long offset, newoffset, mask;						\
   rtx new, temp = NULL_RTX;						\
Index: config/rs6000/rs6000.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.326
diff -u -p -r1.326 rs6000.h
--- config/rs6000/rs6000.h	14 Jun 2004 10:05:07 -0000	1.326
+++ config/rs6000/rs6000.h	19 Jun 2004 16:27:55 -0000
@@ -2028,7 +2028,7 @@ typedef struct rs6000_args
    Implemented on rs6000 by rs6000_legitimize_reload_address.  
    Note that (X) is evaluated twice; this is safe in current usage.  */
    
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN)	     \
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,I,WIN)	     \
 do {									     \
   int win;								     \
   (X) = rs6000_legitimize_reload_address ((X), (MODE), (OPNUM),		     \
Index: config/sh/sh.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/sh/sh.h,v
retrieving revision 1.241
diff -u -p -r1.241 sh.h
--- config/sh/sh.h	11 Jun 2004 18:13:32 -0000	1.241
+++ config/sh/sh.h	19 Jun 2004 16:28:06 -0000
@@ -2528,7 +2528,7 @@ struct sh_args {
    Like for LEGITIMIZE_ADDRESS, for the SH we try to get a normal form
    of the address.  That will allow inheritance of the address reloads.  */
 
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN)	\
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,I,WIN)	\
 {									\
   if (GET_CODE (X) == PLUS						\
       && (GET_MODE_SIZE (MODE) == 4 || GET_MODE_SIZE (MODE) == 8)	\
Index: config/sparc/sparc.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/sparc/sparc.h,v
retrieving revision 1.256
diff -u -p -r1.256 sparc.h
--- config/sparc/sparc.h	14 Jun 2004 14:07:06 -0000	1.256
+++ config/sparc/sparc.h	19 Jun 2004 16:28:26 -0000
@@ -2136,7 +2136,7 @@ do {									\
    Do nothing when generating PIC code and the address is a
    symbolic operand or requires a scratch register.  */
 
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN)     \
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,I,WIN)   \
 do {                                                                    \
   /* Decompose SImode constants into hi+lo_sum.  We do have to 		\
      rerecognize what we produce, so be careful.  */			\
Index: doc/tm.texi
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/doc/tm.texi,v
retrieving revision 1.329
diff -u -p -r1.329 tm.texi
--- doc/tm.texi	11 Jun 2004 18:41:47 -0000	1.329
+++ doc/tm.texi	19 Jun 2004 17:52:25 -0000
@@ -4994,12 +4994,12 @@ fact, it is safe to omit this macro.  Bu
 machine-dependent strategy can generate better code.
 @end defmac
 
-@defmac LEGITIMIZE_RELOAD_ADDRESS (@var{x}, @var{mode}, @var{opnum}, 
@var{type}, @var{ind_levels}, @var{win})
+@defmac LEGITIMIZE_RELOAD_ADDRESS (@var{x}, @var{mode}, @var{opnum}, 
@var{type}, @var{ind_levels}, @var{insn}, @var{win})
 A C compound statement that attempts to replace @var{x}, which is an address
 that needs reloading, with a valid memory address for an operand of mode
 @var{mode}.  @var{win} will be a C statement label elsewhere in the code.
-It is not necessary to define this macro, but it might be useful for
-performance reasons.
+@var{insn} is the insn being reloaded.  It is not necessary to define this
+macro, but it might be useful for performance reasons.
 
 For example, on the i386, it is sometimes possible to use a single
 reload register instead of two by reloading a sum of two pseudo


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