diff options
author | Richard Henderson <rth@redhat.com> | 2001-09-04 22:54:09 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2001-09-04 22:54:09 -0700 |
commit | aead1ca3db61ac3e942e4c57a23d1dfbe3813234 (patch) | |
tree | 1fc8fc8a6a49754c767b4d792fee043b740268fe /gcc | |
parent | ef671f41754b1eef032f3f284b0b1bc8941b7941 (diff) | |
download | gcc-aead1ca3db61ac3e942e4c57a23d1dfbe3813234.zip gcc-aead1ca3db61ac3e942e4c57a23d1dfbe3813234.tar.gz gcc-aead1ca3db61ac3e942e4c57a23d1dfbe3813234.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config/alpha/alpha-protos.h | 5 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 125 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.h | 132 | ||||
-rw-r--r-- | gcc/reload.c | 5 | ||||
-rw-r--r-- | gcc/reload.h | 7 |
6 files changed, 167 insertions, 118 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9e6913c..611fb94 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h index 511bfb6..6696a18 100644 --- a/gcc/config/alpha/alpha-protos.h +++ b/gcc/config/alpha/alpha-protos.h @@ -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, diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 999d050..a7ed116 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -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 diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index d12f581..0af8374 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -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. - - 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; \ - } \ -} + opportunities to optimize the output. */ + +#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) diff --git a/gcc/reload.c b/gcc/reload.c index 9fb19ba..b069d18 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -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; diff --git a/gcc/reload.h b/gcc/reload.h index d9f73e1..edb458b 100644 --- a/gcc/reload.h +++ b/gcc/reload.h @@ -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: */ |