reload.c (find_reloads_address): Try LEGITIMIZE_RELOAD_ADDRESS.

* reload.c (find_reloads_address): Try LEGITIMIZE_RELOAD_ADDRESS.
(move_replacements): New function.
* reload.h: Prototype it.
* alpha.h (LEGITIMIZE_RELOAD_ADDRESS): New definition.

Co-Authored-By: Richard Henderson <rth@cygnus.com>

From-SVN: r18947
This commit is contained in:
Joern Rennecke 1998-04-02 02:42:26 +00:00 committed by Richard Henderson
parent ce4d78eb2f
commit a9a2595b58
5 changed files with 134 additions and 0 deletions

View File

@ -1,3 +1,12 @@
Thu Apr 2 02:37:07 1998 Joern Rennecke (amylaar@cygnus.co.uk)
Richard Henderson <rth@cygnus.com>
* reload.c (find_reloads_address): Try LEGITIMIZE_RELOAD_ADDRESS.
(move_replacements): New function.
* reload.h: Prototype it.
* alpha.h (LEGITIMIZE_RELOAD_ADDRESS): New definition.
Thu Apr 2 01:01:34 1998 Richard Henderson <rth@cygnus.com>
* configure (alpha-*-linuxecoff, alpha-*-linux-gnulibc1):

View File

@ -1467,6 +1467,46 @@ extern void alpha_init_expanders ();
} \
}
/* Try a machine-dependent way of reloading an illegitimate address
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.
For the Alpha, we wish to handle large displacements off a base
register by splitting the addend across an ldah and the mem insn.
This cuts number of extra insns needed from 3 to 1. */
#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
do { \
if (GET_CODE (X) == PLUS \
&& GET_CODE (XEXP (X, 0)) == REG \
&& REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER \
&& REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE) \
&& GET_CODE (XEXP (X, 1)) == CONST_INT) \
{ \
HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \
HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000; \
HOST_WIDE_INT high \
= (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000; \
\
/* Check for 32-bit overflow. */ \
if (high + low != val) \
break; \
\
/* Reload the high part into a base reg; leave the low part \
in the mem directly. */ \
\
X = gen_rtx_PLUS (GET_MODE (X), \
gen_rtx_PLUS (GET_MODE (X), XEXP (X, 0), \
GEN_INT (high)), \
GEN_INT (low)); \
\
push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR, \
BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
OPNUM, TYPE); \
goto WIN; \
} \
} while (0)
/* Go to LABEL if ADDR (a legitimate address expression)
has an effect that depends on the machine mode it is used for.
On the Alpha this is true only for the unaligned modes. We can

View File

@ -4422,6 +4422,24 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
return 0;
}
#ifdef LEGITIMIZE_RELOAD_ADDRESS
do
{
if (memrefloc)
{
LEGITIMIZE_RELOAD_ADDRESS (ad, GET_MODE (*memrefloc), opnum, type,
ind_levels, win);
}
break;
win:
*memrefloc = copy_rtx (*memrefloc);
XEXP (*memrefloc, 0) = ad;
move_replacements (&ad, &XEXP (*memrefloc, 0));
return 1;
}
while (0);
#endif
/* The address is not valid. We have to figure out why. One possibility
is that it is itself a MEM. This can happen when the frame pointer is
being eliminated, a pseudo is not allocated to a hard register, and the
@ -5372,6 +5390,25 @@ copy_replacements (x, y)
}
}
}
/* Change any replacements being done to *X to be done to *Y */
void
move_replacements (x, y)
rtx *x;
rtx *y;
{
int i;
for (i = 0; i < n_replacements; i++)
if (replacements[i].subreg_loc == x)
replacements[i].subreg_loc = y;
else if (replacements[i].where == x)
{
replacements[i].where = y;
replacements[i].subreg_loc = 0;
}
}
/* If LOC was scheduled to be replaced by something, return the replacement.
Otherwise, return *LOC. */

View File

@ -187,6 +187,9 @@ extern void subst_reloads PROTO((void));
the RTL. */
extern void copy_replacements PROTO((rtx, rtx));
/* Change any replacements being done to *X to be done to *Y */
extern void move_replacements PROTO((rtx *x, rtx *y));
/* If LOC was scheduled to be replaced by something, return the replacement.
Otherwise, return *LOC. */
extern rtx find_replacement PROTO((rtx *));

View File

@ -4223,6 +4223,51 @@ address. The compiler has standard ways of doing so in all cases. In
fact, it is safe for this macro to do nothing. But often a
machine-dependent strategy can generate better code.
@findex LEGITIMIZE_RELOAD_ADDRESS
@item LEGITIMIZE_RELOAD_ADDRESS (@var{x}, @var{mode}, @var{opnum}, @var{type}, @var{ind_levels}, @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.
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
registers into a register. On the other hand, for number of RISC
processors offsets are limited so that often an intermediate address
needs to be generated in order to address a stack slot. By defining
LEGITIMIZE_RELOAD_ADDRESS appropriately, the intermediate addresses
generated for adjacent some stack slots can be made identical, and thus
be shared.
@findex strict_memory_address_p
The macro definition may use @code{strict_memory_address_p} to test if
the address has become legitimate.
@findex push_reload
It may use @code{push_reload} to indicate parts that need reloading.
@var{opnum}, @var{type} and @var{ind_levels} are usually suitable to be
passed unaltered to push_reload.
The code generated by this macro should not alter the substructure of
@var{x}. If it transforms @var{x} into a more legitimate form, it
should assign @var{x} (which will always be a C variable) a new value.
This also applies to parts that you change indirectly by calling
@code{push_reload}.
@findex copy_rtx
If you want to change only a part of @var{x}, one standard way of doing
this is to use @code{copy_rtx}. Note, however, that is unshares only a
single level of rtl. Thus, if the part to be changed is not at the
top level, you'll need to replace first the top leve
It is not necessary for this macro to come up with a legitimate
address; but often a machine-dependent strategy can generate better code.
@emph{Note}: This macro should be used with caution. It is necessary
to know something of how reload works in order to effectively use this,
and it is quite easy to produce macros that build in too much knowledge
of reload internals.
@findex GO_IF_MODE_DEPENDENT_ADDRESS
@item GO_IF_MODE_DEPENDENT_ADDRESS (@var{addr}, @var{label})
A C statement or compound statement with a conditional @code{goto