This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RFC,arm] Pass insn to LEGITIMIZE_RELOAD_ADDRESS
- From: Paul Brook <paul at codesourcery dot com>
- To: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Cc: Richard Earnshaw <rearnsha at arm dot com>
- Date: Sat, 19 Jun 2004 18:56:22 +0100
- Subject: [RFC,arm] Pass insn to LEGITIMIZE_RELOAD_ADDRESS
- Organization: CodeSourcery
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