diff options
author | Doug Evans <dje@gnu.org> | 1997-01-21 17:15:54 +0000 |
---|---|---|
committer | Doug Evans <dje@gnu.org> | 1997-01-21 17:15:54 +0000 |
commit | a12f68f4f21713eab33d5adb8c538d1e3a822464 (patch) | |
tree | f46252d0d92d72617c4cff7d3bf736a77fdfb44f | |
parent | e454beb74e176e1f4bff5b2980e646da38af0baf (diff) | |
download | gcc-a12f68f4f21713eab33d5adb8c538d1e3a822464.zip gcc-a12f68f4f21713eab33d5adb8c538d1e3a822464.tar.gz gcc-a12f68f4f21713eab33d5adb8c538d1e3a822464.tar.bz2 |
reload1.c (eliminate_regs, case MINUS): Canonicalize (minus (plus reg const) reg) to (plus (minus reg reg) const).
* reload1.c (eliminate_regs, case MINUS): Canonicalize
(minus (plus reg const) reg) to (plus (minus reg reg) const).
* reload.c (find_reloads_address): Treat (plus (minus reg reg) const)
the same as (plus (plus reg reg) const).
From-SVN: r13539
-rw-r--r-- | gcc/reload.c | 12 | ||||
-rw-r--r-- | gcc/reload1.c | 25 |
2 files changed, 32 insertions, 5 deletions
diff --git a/gcc/reload.c b/gcc/reload.c index 5bb39dc..e1f5f91 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -4368,7 +4368,9 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels) /* If we have an indexed stack slot, there are three possible reasons why it might be invalid: The index might need to be reloaded, the address might have been made by frame pointer elimination and hence have a - constant out of range, or both reasons might apply. + constant out of range, or the address is the result of register + elimination and (plus (plus reg reg) const), which has been + canonicalized from (plus (plus reg const) reg), isn't a valid address. We can easily check for an index needing reload, but even if that is the case, we might also have an invalid constant. To avoid making the @@ -4395,7 +4397,11 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels) innermost PLUS. */ else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT - && GET_CODE (XEXP (ad, 0)) == PLUS + && (GET_CODE (XEXP (ad, 0)) == PLUS + /* MINUS can happen as a result of register elimination of + (minus eliminable reg) which gets canonicalized as + (plus (minus reg reg) const). */ + || GET_CODE (XEXP (ad, 0)) == MINUS) && (XEXP (XEXP (ad, 0), 0) == frame_pointer_rtx #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM || XEXP (XEXP (ad, 0), 0) == hard_frame_pointer_rtx @@ -4406,7 +4412,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels) || XEXP (XEXP (ad, 0), 0) == stack_pointer_rtx) && ! memory_address_p (mode, ad)) { - *loc = ad = gen_rtx (PLUS, GET_MODE (ad), + *loc = ad = gen_rtx (GET_CODE (XEXP (ad, 0)), GET_MODE (ad), plus_constant (XEXP (XEXP (ad, 0), 0), INTVAL (XEXP (ad, 1))), XEXP (XEXP (ad, 0), 1)); diff --git a/gcc/reload1.c b/gcc/reload1.c index b5e9394..d4f2140 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -2853,7 +2853,7 @@ eliminate_regs (x, mem_mode, insn) context. If we have (plus (eliminable) (reg)), we want to produce - (plus (plus (replacement) (reg) (const))). If this was part of a + (plus (plus (replacement) (reg)) (const)). If this was part of a normal add insn, (plus (replacement) (reg)) will be pushed as a reload. This is the desired action. */ @@ -2892,6 +2892,28 @@ eliminate_regs (x, mem_mode, insn) } return x; + case MINUS: + /* If we have (minus (eliminable) (reg)), we want to produce + (plus (minus (replacement) (reg)) (const)). The main reason being + to be consistent with what is done for PLUS. find_reloads_address + assumes that we do this. */ + { + rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn); + rtx new1 = eliminate_regs (XEXP (x, 1), mem_mode, insn); + + if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)) + { + if (GET_CODE (new0) == PLUS) + return gen_rtx (PLUS, GET_MODE (x), + gen_rtx (MINUS, GET_MODE (x), + XEXP (new0, 0), new1), + XEXP (new0, 1)); + else + return gen_rtx (MINUS, GET_MODE (x), new0, new1); + } + } + return x; + case MULT: /* If this is the product of an eliminable register and a constant, apply the distribute law and move the constant out @@ -2920,7 +2942,6 @@ eliminate_regs (x, mem_mode, insn) case CALL: case COMPARE: - case MINUS: case DIV: case UDIV: case MOD: case UMOD: case AND: case IOR: case XOR: |