[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