summaryrefslogtreecommitdiff
path: root/gcc/config/arm/arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r--gcc/config/arm/arm.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 51614396da4..2feac6f45e1 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -6550,9 +6550,26 @@ arm_legitimize_reload_address (rtx *p,
int opnum, int type,
int ind_levels ATTRIBUTE_UNUSED)
{
+ /* We must recognize output that we have already generated ourselves. */
+ if (GET_CODE (*p) == PLUS
+ && GET_CODE (XEXP (*p, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (*p, 0), 0)) == REG
+ && GET_CODE (XEXP (XEXP (*p, 0), 1)) == CONST_INT
+ && GET_CODE (XEXP (*p, 1)) == CONST_INT)
+ {
+ push_reload (XEXP (*p, 0), NULL_RTX, &XEXP (*p, 0), NULL,
+ MODE_BASE_REG_CLASS (mode), GET_MODE (*p),
+ VOIDmode, 0, 0, opnum, (enum reload_type) type);
+ return true;
+ }
+
if (GET_CODE (*p) == PLUS
&& GET_CODE (XEXP (*p, 0)) == REG
&& ARM_REGNO_OK_FOR_BASE_P (REGNO (XEXP (*p, 0)))
+ /* If the base register is equivalent to a constant, let the generic
+ code handle it. Otherwise we will run into problems if a future
+ reload pass decides to rematerialize the constant. */
+ && !reg_equiv_constant (ORIGINAL_REGNO (XEXP (*p, 0)))
&& GET_CODE (XEXP (*p, 1)) == CONST_INT)
{
HOST_WIDE_INT val = INTVAL (XEXP (*p, 1));