[Top][All Lists]
[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
- [avr-gcc-list] Bug 31786 spill in class 'BASE_POINTER_REGS',
Andrew Hutchinson <=