------- Comment #8 from hutchinsonandy at gcc dot gnu dot org  2009-11-02 00:54 
-------
The problem seems related to use of R28+r29 - which is also frame pointer.

avr_hard_regno_mode_ok allows R28 in HIMODE but not any other mode. (This hack
was made to avoid reload problem where r29 was used as well as R28 frame
pointer)

It looks like the "not ok" QI subreg 28/29 of "ok" HImode r28 is not handled
well. 

The mode restriction is ignored for input reload. (Perhaps because reload
decides to use available frame pointer)

The output reload needed is 16bit HImode but must be accessible as two QImode 
subregs. Somehow the mode of output reload gets mangled so we get movw r28,r18


Originally ~2005 the rejection of other modes by avr_hard_regno_mode_ok for r28
was only applied when reload was in progress and frame_pointer_required.

So I reapplied this condition and the bug was solved. This function does not
need frame pointer so r28 and r29 are indeed freely available.

  /* Otherwise disallow all regno/mode combinations that span r28:r29.  */
  if (reload_in_progress && frame_pointer_needed && regno <= (REG_Y + 1) &&
(regno + GET_MODE_SIZE (mode)) >= (REG_Y + 1))
    return 0;


This also produces better code!

One concern is that the modes deemed ok or not are now not constant - and
perhaps is the reason why condition was removed.

In Gcc 4.5 the spill is exactly the same but it uses R16/r17 with the correct
output reload subreg - so seems to figure out that r28 is "not ok" - suggesting
problem is fixed.


This may take a while to resolve, with some further research and testing.


-- 


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

Reply via email to