reload.c (push_reload): Export.
* reload.c (push_reload): Export. * reload.h (push_reload): Declare it. * config/alpha/alpha.h (LEGITIMIZE_ADDRESS): Move out o' line. (LEGITIMIZE_RELOAD_ADDRESS): Likewise. * config/alpha/alpha.c (alpha_legitimize_address): New. (alpha_legitimize_reload_address): Likewise. * config/alpha/alpha-protos.h: Declare them. From-SVN: r45392
This commit is contained in:
parent
ef671f4175
commit
aead1ca3db
|
@ -1,3 +1,14 @@
|
|||
2001-09-04 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* reload.c (push_reload): Export.
|
||||
* reload.h (push_reload): Declare it.
|
||||
|
||||
* config/alpha/alpha.h (LEGITIMIZE_ADDRESS): Move out o' line.
|
||||
(LEGITIMIZE_RELOAD_ADDRESS): Likewise.
|
||||
* config/alpha/alpha.c (alpha_legitimize_address): New.
|
||||
(alpha_legitimize_reload_address): Likewise.
|
||||
* config/alpha/alpha-protos.h: Declare them.
|
||||
|
||||
2001-09-04 Stan Shebs <shebs@apple.com>
|
||||
|
||||
* config/darwin.h (ASM_DECLARE_FUNCTION_NAME): Define.
|
||||
|
|
|
@ -72,6 +72,11 @@ extern int addition_operation PARAMS ((rtx, enum machine_mode));
|
|||
|
||||
extern rtx alpha_tablejump_addr_vec PARAMS ((rtx));
|
||||
extern rtx alpha_tablejump_best_label PARAMS ((rtx));
|
||||
|
||||
extern rtx alpha_legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
|
||||
extern rtx alpha_legitimize_reload_address PARAMS ((rtx, enum machine_mode,
|
||||
int, int, int));
|
||||
|
||||
extern void get_aligned_mem PARAMS ((rtx, rtx *, rtx *));
|
||||
extern rtx get_unaligned_address PARAMS ((rtx, int));
|
||||
extern enum reg_class secondary_reload_class PARAMS ((enum reg_class,
|
||||
|
|
|
@ -42,8 +42,8 @@ Boston, MA 02111-1307, USA. */
|
|||
#include "function.h"
|
||||
#include "toplev.h"
|
||||
#include "ggc.h"
|
||||
#include "tm_p.h"
|
||||
#include "integrate.h"
|
||||
#include "tm_p.h"
|
||||
#include "target.h"
|
||||
#include "target-def.h"
|
||||
|
||||
|
@ -1154,6 +1154,129 @@ alpha_tablejump_best_label (insn)
|
|||
return best_label ? best_label : const0_rtx;
|
||||
}
|
||||
|
||||
/* Try machine-dependent ways of modifying an illegitimate address
|
||||
to be legitimate. If we find one, return the new, valid address. */
|
||||
|
||||
rtx
|
||||
alpha_legitimize_address (x, oldx, mode)
|
||||
rtx x;
|
||||
rtx oldx ATTRIBUTE_UNUSED;
|
||||
enum machine_mode mode ATTRIBUTE_UNUSED;
|
||||
{
|
||||
HOST_WIDE_INT addend;
|
||||
|
||||
/* If the address is (plus reg const_int) and the CONST_INT is not a
|
||||
valid offset, compute the high part of the constant and add it to
|
||||
the register. Then our address is (plus temp low-part-const). */
|
||||
if (GET_CODE (x) == PLUS
|
||||
&& GET_CODE (XEXP (x, 0)) == REG
|
||||
&& GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||
&& ! CONSTANT_ADDRESS_P (XEXP (x, 1)))
|
||||
{
|
||||
addend = INTVAL (XEXP (x, 1));
|
||||
x = XEXP (x, 0);
|
||||
goto split_addend;
|
||||
}
|
||||
|
||||
/* If the address is (const (plus FOO const_int)), find the low-order
|
||||
part of the CONST_INT. Then load FOO plus any high-order part of the
|
||||
CONST_INT into a register. Our address is (plus reg low-part-const).
|
||||
This is done to reduce the number of GOT entries. */
|
||||
if (GET_CODE (x) == CONST
|
||||
&& GET_CODE (XEXP (x, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
|
||||
{
|
||||
addend = INTVAL (XEXP (XEXP (x, 0), 1));
|
||||
x = force_reg (Pmode, XEXP (XEXP (x, 0), 0));
|
||||
goto split_addend;
|
||||
}
|
||||
|
||||
/* If we have a (plus reg const), emit the load as in (2), then add
|
||||
the two registers, and finally generate (plus reg low-part-const) as
|
||||
our address. */
|
||||
if (GET_CODE (x) == PLUS
|
||||
&& GET_CODE (XEXP (x, 0)) == REG
|
||||
&& GET_CODE (XEXP (x, 1)) == CONST
|
||||
&& GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == CONST_INT)
|
||||
{
|
||||
addend = INTVAL (XEXP (XEXP (XEXP (x, 1), 0), 1));
|
||||
x = expand_simple_binop (Pmode, PLUS, XEXP (x, 0),
|
||||
XEXP (XEXP (XEXP (x, 1), 0), 0),
|
||||
NULL_RTX, 1, OPTAB_LIB_WIDEN);
|
||||
goto split_addend;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
split_addend:
|
||||
{
|
||||
HOST_WIDE_INT lowpart = (addend & 0xffff) - 2 * (addend & 0x8000);
|
||||
HOST_WIDE_INT highpart = addend - lowpart;
|
||||
x = expand_simple_binop (Pmode, PLUS, x, GEN_INT (highpart),
|
||||
NULL_RTX, 1, OPTAB_LIB_WIDEN);
|
||||
return plus_constant (x, lowpart);
|
||||
}
|
||||
}
|
||||
|
||||
/* Try a machine-dependent way of reloading an illegitimate address
|
||||
operand. If we find one, push the reload and return the new rtx. */
|
||||
|
||||
rtx
|
||||
alpha_legitimize_reload_address (x, mode, opnum, type, ind_levels)
|
||||
rtx x;
|
||||
enum machine_mode mode ATTRIBUTE_UNUSED;
|
||||
int opnum;
|
||||
int type;
|
||||
int ind_levels ATTRIBUTE_UNUSED;
|
||||
{
|
||||
/* We must recognize output that we have already generated ourselves. */
|
||||
if (GET_CODE (x) == PLUS
|
||||
&& GET_CODE (XEXP (x, 0)) == PLUS
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
|
||||
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
|
||||
&& GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
{
|
||||
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
|
||||
BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
|
||||
opnum, type);
|
||||
return x;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
if (GET_CODE (x) == PLUS
|
||||
&& GET_CODE (XEXP (x, 0)) == REG
|
||||
&& REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
|
||||
&& REGNO_OK_FOR_BASE_P (REGNO (XEXP (x, 0)))
|
||||
&& 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)
|
||||
return NULL_RTX;
|
||||
|
||||
/* 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,
|
||||
BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
|
||||
opnum, type);
|
||||
return x;
|
||||
}
|
||||
|
||||
return NULL_RTX;
|
||||
}
|
||||
|
||||
/* REF is an alignable memory location. Place an aligned SImode
|
||||
reference into *PALIGNED_MEM and the number of bits to shift into
|
||||
*PBITNUM. SCRATCH is a free register for use in reloading out
|
||||
|
|
|
@ -1460,122 +1460,30 @@ do { \
|
|||
GO_IF_LEGITIMATE_ADDRESS.
|
||||
|
||||
It is always safe for this macro to do nothing. It exists to recognize
|
||||
opportunities to optimize the output.
|
||||
opportunities to optimize the output. */
|
||||
|
||||
For the Alpha, there are three cases we handle:
|
||||
|
||||
(1) If the address is (plus reg const_int) and the CONST_INT is not a
|
||||
valid offset, compute the high part of the constant and add it to the
|
||||
register. Then our address is (plus temp low-part-const).
|
||||
(2) If the address is (const (plus FOO const_int)), find the low-order
|
||||
part of the CONST_INT. Then load FOO plus any high-order part of the
|
||||
CONST_INT into a register. Our address is (plus reg low-part-const).
|
||||
This is done to reduce the number of GOT entries.
|
||||
(3) If we have a (plus reg const), emit the load as in (2), then add
|
||||
the two registers, and finally generate (plus reg low-part-const) as
|
||||
our address. */
|
||||
|
||||
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
|
||||
{ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
|
||||
&& ! CONSTANT_ADDRESS_P (XEXP (X, 1))) \
|
||||
{ \
|
||||
HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \
|
||||
HOST_WIDE_INT lowpart = (val & 0xffff) - 2 * (val & 0x8000); \
|
||||
HOST_WIDE_INT highpart = val - lowpart; \
|
||||
rtx high = GEN_INT (highpart); \
|
||||
rtx temp = expand_binop (Pmode, add_optab, XEXP (x, 0), \
|
||||
high, NULL_RTX, 1, OPTAB_LIB_WIDEN); \
|
||||
\
|
||||
(X) = plus_constant (temp, lowpart); \
|
||||
goto WIN; \
|
||||
} \
|
||||
else if (GET_CODE (X) == CONST \
|
||||
&& GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT) \
|
||||
{ \
|
||||
HOST_WIDE_INT val = INTVAL (XEXP (XEXP (X, 0), 1)); \
|
||||
HOST_WIDE_INT lowpart = (val & 0xffff) - 2 * (val & 0x8000); \
|
||||
HOST_WIDE_INT highpart = val - lowpart; \
|
||||
rtx high = XEXP (XEXP (X, 0), 0); \
|
||||
\
|
||||
if (highpart) \
|
||||
high = plus_constant (high, highpart); \
|
||||
\
|
||||
(X) = plus_constant (force_reg (Pmode, high), lowpart); \
|
||||
goto WIN; \
|
||||
} \
|
||||
else if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \
|
||||
&& GET_CODE (XEXP (X, 1)) == CONST \
|
||||
&& GET_CODE (XEXP (XEXP (X, 1), 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (XEXP (X, 1), 0), 1)) == CONST_INT) \
|
||||
{ \
|
||||
HOST_WIDE_INT val = INTVAL (XEXP (XEXP (XEXP (X, 1), 0), 1)); \
|
||||
HOST_WIDE_INT lowpart = (val & 0xffff) - 2 * (val & 0x8000); \
|
||||
HOST_WIDE_INT highpart = val - lowpart; \
|
||||
rtx high = XEXP (XEXP (XEXP (X, 1), 0), 0); \
|
||||
\
|
||||
if (highpart) \
|
||||
high = plus_constant (high, highpart); \
|
||||
\
|
||||
high = expand_binop (Pmode, add_optab, XEXP (X, 0), \
|
||||
force_reg (Pmode, high), \
|
||||
high, 1, OPTAB_LIB_WIDEN); \
|
||||
(X) = plus_constant (high, lowpart); \
|
||||
goto WIN; \
|
||||
} \
|
||||
}
|
||||
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
|
||||
do { \
|
||||
rtx new_x = alpha_legitimize_address (X, OLDX, MODE); \
|
||||
if (new_x) \
|
||||
{ \
|
||||
X = new_x; \
|
||||
goto WIN; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* 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. */
|
||||
macro is used in only one place: `find_reloads_address' in reload.c. */
|
||||
|
||||
#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
|
||||
do { \
|
||||
/* We must recognize output that we have already generated ourselves. */ \
|
||||
if (GET_CODE (X) == PLUS \
|
||||
&& GET_CODE (XEXP (X, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 0)) == REG \
|
||||
&& GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
|
||||
&& GET_CODE (XEXP (X, 1)) == CONST_INT) \
|
||||
{ \
|
||||
push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL, \
|
||||
BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
|
||||
OPNUM, TYPE); \
|
||||
goto WIN; \
|
||||
} \
|
||||
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, \
|
||||
BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
|
||||
OPNUM, TYPE); \
|
||||
goto WIN; \
|
||||
} \
|
||||
#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,WIN) \
|
||||
do { \
|
||||
rtx new_x = alpha_legitimize_reload_address (X, MODE, OPNUM, TYPE, IND_L); \
|
||||
if (new_x) \
|
||||
{ \
|
||||
X = new_x; \
|
||||
goto WIN; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Go to LABEL if ADDR (a legitimate address expression)
|
||||
|
|
|
@ -242,9 +242,6 @@ static int push_secondary_reload PARAMS ((int, rtx, int, int, enum reg_class,
|
|||
#endif
|
||||
static enum reg_class find_valid_class PARAMS ((enum machine_mode, int));
|
||||
static int reload_inner_reg_of_subreg PARAMS ((rtx, enum machine_mode));
|
||||
static int push_reload PARAMS ((rtx, rtx, rtx *, rtx *, enum reg_class,
|
||||
enum machine_mode, enum machine_mode,
|
||||
int, int, int, enum reload_type));
|
||||
static void push_replacement PARAMS ((rtx *, int, enum machine_mode));
|
||||
static void combine_reloads PARAMS ((void));
|
||||
static int find_reusable_reload PARAMS ((rtx *, rtx, enum reg_class,
|
||||
|
@ -845,7 +842,7 @@ reload_inner_reg_of_subreg (x, mode)
|
|||
the two reload-numbers are equal, but the caller should be careful to
|
||||
distinguish them. */
|
||||
|
||||
static int
|
||||
int
|
||||
push_reload (in, out, inloc, outloc, class,
|
||||
inmode, outmode, strict_low, optional, opnum, type)
|
||||
rtx in, out;
|
||||
|
|
|
@ -331,7 +331,12 @@ extern int regno_clobbered_p PARAMS ((unsigned int, rtx, enum machine_mode,
|
|||
int));
|
||||
|
||||
/* Return 1 if X is an operand of an insn that is being earlyclobbered. */
|
||||
int earlyclobber_operand_p PARAMS ((rtx));
|
||||
extern int earlyclobber_operand_p PARAMS ((rtx));
|
||||
|
||||
/* Record one reload that needs to be performed. */
|
||||
extern int push_reload PARAMS ((rtx, rtx, rtx *, rtx *, enum reg_class,
|
||||
enum machine_mode, enum machine_mode,
|
||||
int, int, int, enum reload_type));
|
||||
|
||||
/* Functions in reload1.c: */
|
||||
|
||||
|
|
Loading…
Reference in New Issue