http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50925

--- Comment #11 from denisc at gcc dot gnu.org 2011-12-05 19:08:41 UTC ---
Sorry, wrong button was pressed.

(In reply to comment #8)
> I'm not going to be able to look at it anytime soon, but just some general
> thoughts:

I think that I'm ready to explain the bug.

>   1. Disabling caller-saves probably isn't appropriate.  Just looking at
> codesize isn't the way to evaluate caller-saves either as caller-saves is
> tasked with improving performance, possibly at the expense of codesize.

I'm agree. I don't want to disable caller-saves.

> 
>   2. The first thing someone needs to do is provide information as to why that
> insn needs reloads.  I don't know enough about the AVR to hazard as guess why
> that insn needs reloads.
> 
>   3. Find out where insn 172 comes from.  There are restrictions on the insns
> created by caller-save.  So if caller-save creates a bogus insn, then that
> needs to be investigated.

Generally, caller-save generate right insn.

  1. AVR port have a specific dependency between frame_pointer_needed and 
get_frame_size().
avr_frame_pointer_required_p (void)
{
  return (cfun->calls_alloca
          || cfun->calls_setjmp
          || cfun->has_nonlocal_label
          || crtl->args.info.nregs == 0
          || get_frame_size () > 0);
}

  2. reload calls the `setup_save_areas ()' and after that get_frame_size ()
equal to 2, but frame_pointer_needed is 0.
It's wrong for AVR port (If dependency between frame_pointer_needed and
get_frame_size() is permitted by GCC core).

  3. After that caller-save generate right save/restore insns for save to frame
slot and restore from it. Like this (r28 is a frame pointer):
(insn 162 77 163 10 (set (reg:QI 18 r18)
        (mem/c:QI (plus:HI (reg/f:HI 28 r28)
                (const_int 1 [0x1])) [8 S1 A8])) /mnt/d/avr-work/tst/nl.c:120
20 {movqi_insn}
     (nil))

  4. After that the following code was executed:
      /* If needed, eliminate any eliminable registers.  */
      if (num_eliminable || num_eliminable_invariants)
        did_elimination = eliminate_regs_in_insn (insn, 0);
And right insns converted to wrong (__SP_L__ can not be used as a pointer):
(insn 162 77 163 10 (set (reg:QI 18 r18)
        (mem/c:QI (plus:HI (reg/f:HI 32 __SP_L__)
                (const_int 1 [0x1])) [8 S1 A8])) /mnt/d/avr-work/tst/nl.c:120
20 {movqi_insn}
     (nil))
Here we have a wrong elimination FP->SP because frame_pointer_needed was not
recalculated earlier. 

  5. relod have the following fragment:
      if (caller_save_needed)
    setup_save_areas ();

      /* If we allocated another stack slot, redo elimination bookkeeping.  */
      if (something_was_spilled || starting_frame_size != get_frame_size ())
    continue;
-------------------------------
But it's not resolve the problem. frame_pointer_needed isn't recalculated.
Call to `update_eliminables ()' seems as a right solution.

Reply via email to