Commit aead1ca3 by Richard Henderson Committed by Richard Henderson

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
parent ef671f41
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> 2001-09-04 Stan Shebs <shebs@apple.com>
* config/darwin.h (ASM_DECLARE_FUNCTION_NAME): Define. * config/darwin.h (ASM_DECLARE_FUNCTION_NAME): Define.
......
...@@ -72,6 +72,11 @@ extern int addition_operation PARAMS ((rtx, enum machine_mode)); ...@@ -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_addr_vec PARAMS ((rtx));
extern rtx alpha_tablejump_best_label 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 void get_aligned_mem PARAMS ((rtx, rtx *, rtx *));
extern rtx get_unaligned_address PARAMS ((rtx, int)); extern rtx get_unaligned_address PARAMS ((rtx, int));
extern enum reg_class secondary_reload_class PARAMS ((enum reg_class, extern enum reg_class secondary_reload_class PARAMS ((enum reg_class,
......
...@@ -42,8 +42,8 @@ Boston, MA 02111-1307, USA. */ ...@@ -42,8 +42,8 @@ Boston, MA 02111-1307, USA. */
#include "function.h" #include "function.h"
#include "toplev.h" #include "toplev.h"
#include "ggc.h" #include "ggc.h"
#include "tm_p.h"
#include "integrate.h" #include "integrate.h"
#include "tm_p.h"
#include "target.h" #include "target.h"
#include "target-def.h" #include "target-def.h"
...@@ -1154,6 +1154,129 @@ alpha_tablejump_best_label (insn) ...@@ -1154,6 +1154,129 @@ alpha_tablejump_best_label (insn)
return best_label ? best_label : const0_rtx; 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 /* REF is an alignable memory location. Place an aligned SImode
reference into *PALIGNED_MEM and the number of bits to shift into reference into *PALIGNED_MEM and the number of bits to shift into
*PBITNUM. SCRATCH is a free register for use in reloading out *PBITNUM. SCRATCH is a free register for use in reloading out
......
...@@ -1460,120 +1460,28 @@ do { \ ...@@ -1460,120 +1460,28 @@ do { \
GO_IF_LEGITIMATE_ADDRESS. GO_IF_LEGITIMATE_ADDRESS.
It is always safe for this macro to do nothing. It exists to recognize 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) \ #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
{ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \ do { \
&& GET_CODE (XEXP (X, 1)) == CONST_INT \ rtx new_x = alpha_legitimize_address (X, OLDX, MODE); \
&& ! CONSTANT_ADDRESS_P (XEXP (X, 1))) \ if (new_x) \
{ \
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)); \ X = new_x; \
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; \ goto WIN; \
} \ } \
} } while (0)
/* Try a machine-dependent way of reloading an illegitimate address /* Try a machine-dependent way of reloading an illegitimate address
operand. If we find one, push the reload and jump to WIN. This 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. 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) \ #define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,WIN) \
do { \ do { \
/* We must recognize output that we have already generated ourselves. */ \ rtx new_x = alpha_legitimize_reload_address (X, MODE, OPNUM, TYPE, IND_L); \
if (GET_CODE (X) == PLUS \ if (new_x) \
&& 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)); \ X = new_x; \
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; \ goto WIN; \
} \ } \
} while (0) } while (0)
......
...@@ -242,9 +242,6 @@ static int push_secondary_reload PARAMS ((int, rtx, int, int, enum reg_class, ...@@ -242,9 +242,6 @@ static int push_secondary_reload PARAMS ((int, rtx, int, int, enum reg_class,
#endif #endif
static enum reg_class find_valid_class PARAMS ((enum machine_mode, int)); 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 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 push_replacement PARAMS ((rtx *, int, enum machine_mode));
static void combine_reloads PARAMS ((void)); static void combine_reloads PARAMS ((void));
static int find_reusable_reload PARAMS ((rtx *, rtx, enum reg_class, static int find_reusable_reload PARAMS ((rtx *, rtx, enum reg_class,
...@@ -845,7 +842,7 @@ reload_inner_reg_of_subreg (x, mode) ...@@ -845,7 +842,7 @@ reload_inner_reg_of_subreg (x, mode)
the two reload-numbers are equal, but the caller should be careful to the two reload-numbers are equal, but the caller should be careful to
distinguish them. */ distinguish them. */
static int int
push_reload (in, out, inloc, outloc, class, push_reload (in, out, inloc, outloc, class,
inmode, outmode, strict_low, optional, opnum, type) inmode, outmode, strict_low, optional, opnum, type)
rtx in, out; rtx in, out;
......
...@@ -331,7 +331,12 @@ extern int regno_clobbered_p PARAMS ((unsigned int, rtx, enum machine_mode, ...@@ -331,7 +331,12 @@ extern int regno_clobbered_p PARAMS ((unsigned int, rtx, enum machine_mode,
int)); int));
/* Return 1 if X is an operand of an insn that is being earlyclobbered. */ /* 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: */ /* Functions in reload1.c: */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment