diff options
author | Richard Henderson <rth@redhat.com> | 2001-09-05 01:43:13 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2001-09-05 01:43:13 -0700 |
commit | a39bdefc84b72b00150490310e4c1c1cd6b449f2 (patch) | |
tree | 94e6fdd1dbda205e0dcbd348662c8748bd6fa2a0 | |
parent | d4fbd953e8930cc804537cc028dc6c5eef9b57dd (diff) | |
download | gcc-a39bdefc84b72b00150490310e4c1c1cd6b449f2.zip gcc-a39bdefc84b72b00150490310e4c1c1cd6b449f2.tar.gz gcc-a39bdefc84b72b00150490310e4c1c1cd6b449f2.tar.bz2 |
alpha.c (alpha_legitimate_address_p): New.
* config/alpha/alpha.c (alpha_legitimate_address_p): New.
* config/alpha/alpha-protos.h: Declare it.
* config/alpha/alpha.h (GO_IF_LEGITIMATE_ADDRESS): Move to c file.
(NONSTRICT_REG_OK_FOR_BASE_P): Rename from non-strict macro.
(NONSTRICT_REG_OK_FP_BASE_P): Likewise.
(STRICT_REG_OK_FOR_BASE_P): Rename from strict macro.
(REG_OK_FOR_BASE_P): Select one of the above.
From-SVN: r45405
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/config/alpha/alpha-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 71 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.h | 100 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.md | 2 |
5 files changed, 106 insertions, 78 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 93113e7..7554869 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2001-09-05 Richard Henderson <rth@redhat.com> + + * config/alpha/alpha.c (alpha_legitimate_address_p): New. + * config/alpha/alpha-protos.h: Declare it. + * config/alpha/alpha.h (GO_IF_LEGITIMATE_ADDRESS): Move to c file. + (NONSTRICT_REG_OK_FOR_BASE_P): Rename from non-strict macro. + (NONSTRICT_REG_OK_FP_BASE_P): Likewise. + (STRICT_REG_OK_FOR_BASE_P): Rename from strict macro. + (REG_OK_FOR_BASE_P): Select one of the above. + 2001-09-05 Richard Sandiford <rsandifo@redhat.com> * config/mips/t-elf (EXTRA_PARTS): Use EXTRA_MULTILIB_PARTS instead. diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h index 025f3af..7de2c62 100644 --- a/gcc/config/alpha/alpha-protos.h +++ b/gcc/config/alpha/alpha-protos.h @@ -73,6 +73,7 @@ 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 bool alpha_legitimate_address_p PARAMS ((enum machine_mode, rtx, int)); 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)); diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index ca4be61..45b6f72 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -1154,6 +1154,77 @@ alpha_tablejump_best_label (insn) return best_label ? best_label : const0_rtx; } +/* legitimate_address_p recognizes an RTL expression that is a valid + memory address for an instruction. The MODE argument is the + machine mode for the MEM expression that wants to use this address. + + For Alpha, we have either a constant address or the sum of a + register and a constant address, or just a register. For DImode, + any of those forms can be surrounded with an AND that clear the + low-order three bits; this is an "unaligned" access. */ + +bool +alpha_legitimate_address_p (mode, x, strict) + enum machine_mode mode; + rtx x; + int strict; +{ + /* If this is an ldq_u type address, discard the outer AND. */ + if (mode == DImode + && GET_CODE (x) == AND + && GET_CODE (XEXP (x, 1)) == CONST_INT + && INTVAL (XEXP (x, 1)) == -8) + x = XEXP (x, 0); + + /* Discard non-paradoxical subregs. */ + if (GET_CODE (x) == SUBREG + && (GET_MODE_SIZE (GET_MODE (x)) + < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))) + x = SUBREG_REG (x); + + /* Unadorned general registers are valid. */ + if (REG_P (x) + && (strict + ? STRICT_REG_OK_FOR_BASE_P (x) + : NONSTRICT_REG_OK_FOR_BASE_P (x))) + return true; + + /* Constant addresses (i.e. +/- 32k) are valid. */ + if (CONSTANT_ADDRESS_P (x)) + return true; + + /* Register plus a small constant offset is valid. */ + if (GET_CODE (x) == PLUS) + { + rtx ofs = XEXP (x, 1); + x = XEXP (x, 0); + + /* Discard non-paradoxical subregs. */ + if (GET_CODE (x) == SUBREG + && (GET_MODE_SIZE (GET_MODE (x)) + < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))) + x = SUBREG_REG (x); + + if (REG_P (x)) + { + if (! strict + && NONSTRICT_REG_OK_FP_BASE_P (x) + && GET_CODE (ofs) == CONST_INT) + return true; + if ((strict + ? STRICT_REG_OK_FOR_BASE_P (x) + : NONSTRICT_REG_OK_FOR_BASE_P (x)) + && CONSTANT_ADDRESS_P (ofs)) + return true; + } + else if (GET_CODE (x) == ADDRESSOF + && GET_CODE (ofs) == CONST_INT) + return true; + } + + return false; +} + /* Try machine-dependent ways of modifying an illegitimate address to be legitimate. If we find one, return the new, valid address. */ diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index 0af8374..c320701 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -1359,15 +1359,13 @@ do { \ After reload, it makes no difference, since pseudo regs have been eliminated by then. */ -#ifndef REG_OK_STRICT - /* Nonzero if X is a hard reg that can be used as an index or if it is a pseudo reg. */ #define REG_OK_FOR_INDEX_P(X) 0 /* Nonzero if X is a hard reg that can be used as a base reg or if it is a pseudo reg. */ -#define REG_OK_FOR_BASE_P(X) \ +#define NONSTRICT_REG_OK_FOR_BASE_P(X) \ (REGNO (X) < 32 || REGNO (X) == 63 || REGNO (X) >= FIRST_PSEUDO_REGISTER) /* ??? Nonzero if X is the frame pointer, or some virtual register @@ -1375,92 +1373,40 @@ do { \ have offsets greater than 32K. This is done because register elimination offsets will change the hi/lo split, and if we split before reload, we will require additional instructions. */ -#define REG_OK_FP_BASE_P(X) \ +#define NONSTRICT_REG_OK_FP_BASE_P(X) \ (REGNO (X) == 31 || REGNO (X) == 63 \ || (REGNO (X) >= FIRST_PSEUDO_REGISTER \ && REGNO (X) < LAST_VIRTUAL_REGISTER)) -#else - -/* Nonzero if X is a hard reg that can be used as an index. */ -#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) - /* Nonzero if X is a hard reg that can be used as a base reg. */ -#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) - -#define REG_OK_FP_BASE_P(X) 0 +#define STRICT_REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) +#ifdef REG_OK_STRICT +#define REG_OK_FOR_BASE_P(X) STRICT_REG_OK_FOR_BASE_P (X) +#else +#define REG_OK_FOR_BASE_P(X) NONSTRICT_REG_OK_FOR_BASE_P (X) #endif -/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression - that is a valid memory address for an instruction. - The MODE argument is the machine mode for the MEM expression - that wants to use this address. - - For Alpha, we have either a constant address or the sum of a register - and a constant address, or just a register. For DImode, any of those - forms can be surrounded with an AND that clear the low-order three bits; - this is an "unaligned" access. - - First define the basic valid address. */ - -#define GO_IF_LEGITIMATE_SIMPLE_ADDRESS(MODE, X, ADDR) \ -{ \ - rtx tmp = (X); \ - if (GET_CODE (tmp) == SUBREG \ - && (GET_MODE_SIZE (GET_MODE (tmp)) \ - < GET_MODE_SIZE (GET_MODE (SUBREG_REG (tmp))))) \ - tmp = SUBREG_REG (tmp); \ - if (REG_P (tmp) && REG_OK_FOR_BASE_P (tmp)) \ - goto ADDR; \ - if (CONSTANT_ADDRESS_P (X)) \ - goto ADDR; \ - if (GET_CODE (X) == PLUS) \ - { \ - tmp = XEXP (X, 0); \ - if (GET_CODE (tmp) == SUBREG \ - && (GET_MODE_SIZE (GET_MODE (tmp)) \ - < GET_MODE_SIZE (GET_MODE (SUBREG_REG (tmp))))) \ - tmp = SUBREG_REG (tmp); \ - if (REG_P (tmp)) \ - { \ - if (REG_OK_FP_BASE_P (tmp) \ - && GET_CODE (XEXP (X, 1)) == CONST_INT) \ - goto ADDR; \ - if (REG_OK_FOR_BASE_P (tmp) \ - && CONSTANT_ADDRESS_P (XEXP (X, 1))) \ - goto ADDR; \ - } \ - else if (GET_CODE (tmp) == ADDRESSOF \ - && CONSTANT_ADDRESS_P (XEXP (X, 1))) \ - goto ADDR; \ - } \ -} - -/* Now accept the simple address, or, for DImode only, an AND of a simple - address that turns off the low three bits. */ +/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression that is a + valid memory address for an instruction. */ -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ GO_IF_LEGITIMATE_SIMPLE_ADDRESS (MODE, X, ADDR); \ - if ((MODE) == DImode \ - && GET_CODE (X) == AND \ - && GET_CODE (XEXP (X, 1)) == CONST_INT \ - && INTVAL (XEXP (X, 1)) == -8) \ - GO_IF_LEGITIMATE_SIMPLE_ADDRESS (MODE, XEXP (X, 0), ADDR); \ -} +#ifdef REG_OK_STRICT +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, WIN) \ +do { \ + if (alpha_legitimate_address_p (MODE, X, 1)) \ + goto WIN; \ +} while (0) +#else +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, WIN) \ +do { \ + if (alpha_legitimate_address_p (MODE, X, 0)) \ + goto WIN; \ +} while (0) +#endif /* Try machine-dependent ways of modifying an illegitimate address to be legitimate. If we find one, return the new, valid address. - This macro is used in only one place: `memory_address' in explow.c. - - OLDX is the address as it was before break_out_memory_refs was called. - In some cases it is useful to look at this to decide what needs to be done. - - MODE and WIN are passed so that this macro can use - GO_IF_LEGITIMATE_ADDRESS. - - It is always safe for this macro to do nothing. It exists to recognize - opportunities to optimize the output. */ + This macro is used in only one place: `memory_address' in explow.c. */ #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \ do { \ diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 8745803..828024b 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -663,7 +663,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (match_operand:DI 1 "reg_no_subreg_operand" "r") (match_operand:DI 2 "const_int_operand" "n")))] - "REG_OK_FP_BASE_P (operands[1]) + "NONSTRICT_REG_OK_FP_BASE_P (operands[1]) && INTVAL (operands[2]) >= 0 /* This is the largest constant an lda+ldah pair can add, minus an upper bound on the displacement between SP and AP during |