On Mon, Oct 29, 2012 at 8:15 AM, Richard Sandiford
<[email protected]> wrote:
> "H.J. Lu" <[email protected]> writes:
>> Hi,
>>
>> This patch changes get_elimination to check register number instead of
>> RTX. Tested on Linux/x32 with -maddress-mode=long. OK to install?
>
> FWIW, this doesn't sound right to me, at least not without more justification.
> The idea is that things like frame_pointer_rtx are supposed to be unique,
> so the original code:
>
>> if ((ep = elimination_map[hard_regno]) != NULL)
>> - return ep->from_rtx != reg ? NULL : ep;
>> from != hard_regno ? NULL : ep;
>
> ought to be correct in itself. reload did the same thing:
>
> for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS];
> ep++)
> if (ep->from_rtx == x && ep->can_eliminate)
> return plus_constant (Pmode, ep->to_rtx, ep->previous_offset);
>
> It sounds on the face of it like the bug is elsewhere.
>
LRA has
if (REG_P (reg) && (ep = get_elimination (reg)) != NULL)
{
rtx to_rtx = replace_p ? ep->to_rtx : ep->from_rtx;
if (! replace_p)
{
offset += (ep->offset - ep->previous_offset);
offset = trunc_int_for_mode (offset, GET_MODE (plus_cst_src));
}
if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG)
to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)), to_rtx);
Reload has
rtx to_rtx = ep->to_rtx;
offset += ep->offset;
offset = trunc_int_for_mode (offset, GET_MODE (plus_cst_src));
if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG)
to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)),
to_rtx);
(gdb) call debug_rtx (ep->to_rtx)
(reg/f:DI 7 sp)
(gdb) call debug_rtx (ep->from_rtx)
(reg/f:DI 16 argp)
(gdb)
gen_lowpart returns (reg/f:DI 7 sp) for reload and (reg:SI 16 argp)
for LRA. They are caused by
if (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
/* We should convert arg register in LRA after the elimination
if it is possible. */
&& xregno == ARG_POINTER_REGNUM
&& ! lra_in_progress)
return -1;
It doesn't work in this case.
--
H.J.