aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2001-09-05 08:43:13 +0000
committerRichard Henderson <rth@redhat.com>2001-09-05 08:43:13 +0000
commitee92fde2ad2f42e3361a695ebf00d71f4525487a (patch)
tree94e6fdd1dbda205e0dcbd348662c8748bd6fa2a0
parent0c0ebddfbde362e5c9de5c62843cd29695aaa628 (diff)
* 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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@45405 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/alpha/alpha-protos.h1
-rw-r--r--gcc/config/alpha/alpha.c71
-rw-r--r--gcc/config/alpha/alpha.h100
-rw-r--r--gcc/config/alpha/alpha.md2
5 files changed, 106 insertions, 78 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 93113e7d9d6..7554869b88f 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 025f3af5e87..7de2c62d717 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 ca4be61da34..45b6f72472d 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 0af83743c29..c320701d37d 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 87458038c4b..828024b37a1 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