avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-gcc-list] Bug 31786 spill in class 'BASE_POINTER_REGS'


From: Andrew Hutchinson
Subject: [avr-gcc-list] Bug 31786 spill in class 'BASE_POINTER_REGS'
Date: Tue, 01 Jan 2008 15:11:17 -0500
User-agent: Thunderbird 2.0.0.9 (Windows/20071031)

Its been a while since I played with this but I looked again at some of the AVR GCC bugs

In particular 31786 - which is one example of where we get fatal  error of :

error: unable to find a register to spill in class 'BASE_POINTER_REGS'

This is a nasty bug as it comes and goes with optimisation changes and there are no robust work arounds. reload in GCC is a magic bit that replaces pseudo registers with real ones - or stack slots.

The problem occurs when reload tries to replace a stack address (SP+1) with one that is valid for AVR (Y+1) or (Z+1).

There are only two base pointer registers Y (R28,29) and Z(R30,3). AVR backend tells reload to use these via LEGITIMIZE_RELOAD_ADDRESS
But if they are both already in use, we get the ICE.

The problem typically occurs when R30,31 is used for indirect calls (function pointer) or EEPROM/Assembler macros. (leaving only R28)

This bug testcase has a indirect call - which must use Z. "count" and the index 'i' are potentially on the stack. Which accounts for R28

extern void (*array_start []) (void);
extern void (*array_end []) (void);

void
init_array (void)
{
 int count;
 int i;
 count = array_end - array_start;
 for (i = 0; i < count; i++)
   array_start[i] ();
}


But i have not been able to figure out why it could not reuse R28. Perhaps R28 is tied up with 'array_start'?

The Gcc dump files don't disclose the RTL instruction sequence - the failed instruction was one "reload" had added since the last pass (and last dump file). However, the dump does indicate R28 was used successfully for a prior reload of SP+1 (which begs the question why reload could not re-use this)

In attempt to find out whats going on, I disabled the of AVR reload of memory addresses by hacking LEGITIMIZE_RELOAD_ADDRESS. This lets GCC take care of it (if it can). Went I rebuilt GCC I got a different error - in gcc libraries. This involved the *movqi pattern failing where gcc created RTL requiring instruction to perform mem(R26+1) = r21. It fails because we reject base pointer indexing unless it is Y or Z (as per AVR instructions). The backend function that rejects this is "legitimate_address_p()."

From prior work I remembered that the backend has a great deal of assembler snippets to cover strange moves. Indeed it has patterns that permit using R26 (with some additions) as base pointer. So I added second hack to permit X as "legitmate_address" - and gcc built ok.

Reviewing the original bug 31786 , I now get good code. Going back over dump files, I still cant tell why R28 was not available. The problem instruction that needed reload and some others got eliminated soon after by reload. So it never needed them! (Probably because reload finally eliminated the stack slot by using spare register.) So I still need to look further why R28 could not be re-used.

I am of the opinion that we should indeed permit R26 to be used as index (and maybe others). I believe we can still make gcc prefer Y&Z - if it doesnt already. If so there should be no penalty in code size and speed (in fact it might be better). Simplistically, the only time R26 would be used in this manner would be where we currently get fatal error.

I have further opinion that LEGITIMIZE_RELOAD_ADDRESS is doing to much. Looking at other ports, they only seem to attempt to adjust pointers to account for large offsets eg. (SP+99) - and leave rest to GCC.

I have compiled some other code and compared to Winavr, and so far, all is ok. I could do with some help though in checking for regressions and forming a bench mark for code size effects.


Comments?


Andy Hutchinson










reply via email to

[Prev in Thread] Current Thread [Next in Thread]