[Bug middle-end/50251] [4.7 Regression] Revision 178353 caused many test failures
vries at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Thu Sep 1 16:30:00 GMT 2011
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50251
--- Comment #5 from vries at gcc dot gnu.org 2011-09-01 16:29:16 UTC ---
Created attachment 25166
--> http://gcc.gnu.org/bugzilla/attachment.cgi?id=25166
ira dump
and after ira, the reference to framereg is still there:
...
(insn 29 28 30 6 (set (reg:SI 0 ax [orig:63 D.2099 ] [63])
(mem/s:SI (plus:SI (reg/f:SI 20 frame)
(const_int -12 [0xfffffffffffffff4])) [2 D.2129+20 S4 A32]))
20010209-1.c:16 64 {*movsi_internal}
(nil))
...
Normally, framereg gets eliminated in ira using either of the following 2
rules:
...
{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} \
...
For main, ix86_can_eliminate limits this to only the first rule:
...
static bool
ix86_can_eliminate (const int from, const int to)
{
if (stack_realign_fp)
return ((from == ARG_POINTER_REGNUM
&& to == HARD_FRAME_POINTER_REGNUM)
|| (from == FRAME_POINTER_REGNUM
&& to == STACK_POINTER_REGNUM));
else
return to == STACK_POINTER_REGNUM ? !frame_pointer_needed : true;
}
...
stack_realign_fp is true for main, so for 'from == FRAME_POINTER_REGNUM', only
'to == STACK_POINTER_REGNUM' is allowed.
reload then itself switches off the first rule here:
...
/* If we have some registers we think can be eliminated, scan all insns to
see if there is an insn that sets one of these registers to something
other than itself plus a constant. If so, the register cannot be
eliminated. Doing this scan here eliminates an extra pass through the
main reload loop in the most common case where register elimination
cannot be done. */
for (insn = first; insn && num_eliminable; insn = NEXT_INSN (insn))
if (INSN_P (insn))
note_stores (PATTERN (insn), mark_not_eliminable, NULL);
...
due to the stack restore:
...
(insn 32 31 33 6 (set (reg/f:SI 7 sp)
(reg/f:SI 59 [ saved_stack.3D.2111 ])) 64 {*movsi_internal}
(expr_list:REG_DEAD (reg/f:SI 59 [ saved_stack.3D.2111 ])
(expr_list:REG_ARGS_SIZE (const_int 0 [0])
(nil))))
...
reload then notes that there is no way to eliminate framereg and sets framereg
in bad_spill_regs_global
...
if (! can_eliminate)
spill_hard_reg (from, 1);
...
The reloads for insn 29 are this, and framereg is still used:
...
Reloads for insn # 29
Reload 0: reload_in (SI) = (mem/s:SI (plus:SI (reg/f:SI 20 frame)
(const_int -12))
[2 D.2129+20 S4 A32])
GENERAL_REGS, RELOAD_FOR_INPUT (opnum = 1), optional
reload_in_reg: (mem/s:SI (plus:SI (reg/f:SI 20 frame)
(const_int -12))
[2 D.2129+20 S4 A32])
...
The documentation for HARD_FRAME_POINTER_REGNUM says the following:
...
When this macro is defined, you must also indicate in your definition of
ELIMINABLE_REGS how to eliminate FRAME_POINTER_REGNUM into either
HARD_FRAME_POINTER_REGNUM or STACK_POINTER_REGNUM.
...
I don't know whether ix86_can_eliminate in the current state violates this
rule, but modifying ix86_can_eliminate to allow the
'FRAME_POINTER_REGNUM -> HARD_FRAME_POINTER_REGNUM' elimination allows the
compilation to succeed and the executable to run successfully.
More information about the Gcc-bugs
mailing list