This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RFA]: Fix pb in find_reloads_subreg_address()
- To: gcc-patches at gcc dot gnu dot org
- Subject: [RFA]: Fix pb in find_reloads_subreg_address()
- From: Stephane Carrez <Stephane dot Carrez at worldnet dot fr>
- Date: Sat, 24 Feb 2001 20:11:09 +0100
Hi!
I found a problem in the reload pass, in find_reloads_subreg_address()
the type of the reload is changed which is wrong.
For 68HC11 target, the following insn:
(insn 531 527 534 (parallel[
(set (mem/f:DF (reg/f:HI 53) 0)
(subreg:DF (reg/v:DI 55) 0))
(clobber (scratch:HI))
] ) 11 {movdf} (insn_list 527 (nil))
(expr_list:REG_DEAD (reg/v:DI 55)
(expr_list:REG_UNUSED (scratch:HI)
(nil))))
has these registers (reg_equiv_memory_loc):
reg:HI 53 => (mem:HI (plus:HI (reg/f:HI 46 *sframe)
(const_int 17 [0x11])) 0)
reg:DI 55 => (mem:DI (plus:HI (reg/f:HI 46 *sframe)
(const_int 19 [0x13])) 0)
It generates the following reloads:
Reload 0: reload_in (HI) = (reg/f:HI 9 *_.frame)
A_REGS, RELOAD_FOR_OPADDR_ADDR (opnum = 0)
reload_in_reg: (reg/f:HI 9 *_.frame)
reload_reg_rtx: (reg:HI 2 y)
Reload 1: reload_in (HI) = (mem:HI (plus:HI (reg/f:HI 9 *_.frame)
(const_int 17 [0x11])) 0)
A_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0), can't combine
reload_in_reg: (reg/f:HI 53)
reload_reg_rtx: (reg:HI 2 y)
Reload 2: A_REGS, RELOAD_FOR_OPADDR_ADDR (opnum = 1)
reload_in_reg: (reg/f:HI 9 *_.frame)
Reload 3: reload_out (DF) = (mem/f:DF (reg/f:HI 53) 0)
NO_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional
reload_out_reg: (mem/f:DF (reg/f:HI 53) 0)
Reload 4: reload_out (HI) = (scratch:HI)
D_REGS, RELOAD_FOR_INSN (opnum = 2)
reload_out_reg: (scratch:HI)
reload_reg_rtx: (reg:HI 1 d)
Reload 0 and 1 are for (reg:HI 53).
Reload 2 is for (reg:DI 55).
Reload 4 is the scratch.
And the insn is reloaded as follows:
(insn 531 1052 534 (parallel[
(set (mem/f:DF (reg:HI 2 y) 0)
(mem:DF (plus:HI (reg:HI 2 y)
(const_int 19 [0x13])) 0))
(clobber (reg:HI 1 d))
] ) 11 {movdf} (insn_list 527 (nil))
(expr_list:REG_DEAD (reg/v:DI 55)
(expr_list:REG_UNUSED (reg:HI 1 d)
(nil))))
This is wrong because the reload 0 and reload 2 are using
the same register (reg:HI 2 y). This is so because the
reload 2 is specified with RELOAD_FOR_OPADDR_ADDR which indicates
that the lifetime of this reload ends with RELOAD_FOR_OPERAND_ADDRESS.
(nothing wrong in reload1.c)
I tracked down the problem in find_reloads() and discovered that
the problem is in find_reloads_subreg_address(). This function
is called for '(subreg:DF (reg/v:DI 55) 0)' with type=RELOAD_FOR_INPUT_ADDRESS,
and it calls find_reloads_address() as follows (reload.c, line 5683):
find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
&XEXP (tem, 0), opnum,
ADDR_TYPE (type),
ind_levels, insn);
and 'tem' is the reg_equiv_memory_loc[] of the register 55 (+ register
elimination,...). Due to ADDR_TYPE (type), the type of reloads
generated for 'tem' is 'RELOAD_FOR_INPADDR_ADDRESS'. This is wrong
because at the end this will be changed to RELOAD_FOR_OPADDR_ADDR,
the type is still RELOAD_FOR_INPUT_ADDRESS (which is what 'tem' is really).
The good call is:
find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
&XEXP (tem, 0), opnum,
type,
ind_levels, insn);
This is also much more coherent with the way the (REG N) are handled
in find_reloads_toplev(): the register is replaced by its corresponding
reg_equiv_memory_loc[] and find_reloads_address() is called with
the *same* type. See line 4262.
Can you integrate or approve this patch for the 3.0 branch?
Thanks,
Stephane
2001-02-24 Stephane Carrez <Stephane.Carrez@worldnet.fr>
* reload.c (find_reloads_subreg_address): Call find_reloads_address
with the same reload type.
--- /src/gnu/cygnus/gcc/gcc/reload.c Sun Jan 28 09:19:22 2001
+++ gcc/reload.c Sat Feb 24 19:35:15 2001
@@ -5681,7 +5681,7 @@ find_reloads_subreg_address (x, force_re
}
find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
- &XEXP (tem, 0), opnum, ADDR_TYPE (type),
+ &XEXP (tem, 0), opnum, type,
ind_levels, insn);
/* If this is not a toplevel operand, find_reloads doesn't see