Help: Register allocator sets up frame at low register pressure (PR 50775)
Georg-Johann Lay
avr@gjlay.de
Tue Oct 25 13:19:00 GMT 2011
With the following, small C test program
typedef struct
{
unsigned char a, b, c, d;
} s_t;
unsigned char func1 (s_t *x, s_t *y, s_t *z)
{
unsigned char s = 0;
s += x->a;
s += y->a;
s += z->a;
s += x->b;
s += y->b;
s += z->b;
s += x->c;
s += y->c;
s += z->c;
return s;
}
there is a frame pointer set up for no apparent reason.
The machine for which this code is compiled for (AVR) has just few pointer
registers and taking away one of them to use it as frame pointer leads to
severe performance degradation in many real-world programs: moving from/to
memory is more expensive than movon around registers, setting up a frame is
expensive and taking away 1 of 2 address registers is expensive.
What I tried and what did not fix it:
- increase targetm.memory_move_cost (up to unsane value)
- play around with targetm.class_likely_spilled_p
The program is compiled with
$ avr-gcc in.c -S -Os -fdump-rtl-ira-details -fdump-rtl-postreload-details
-mmcu=avr4 -mstrict-X
with avr-gcc from current trunk SVN r180399.
The issue is that AVR has only 3 pointer registers X, Y, and Z with the
following addressing capabilities:
*X, *X++, *--X (R27:R26, call-clobbered)
*Y, *Y++, *--Y, *(Y+const) (R28:R29, call-saved, frame pointer)
*Z, *Z++, *--Z, *(Z+const) (R30:R31, call-clobbered)
Older version of the compiler prior to 4.7 trunk r179993 allowed a fake
addressing mode *(X+const) and emulated it by emitting appropriate instructions
sequence like
X = X + const
r = *X
X = X - const
which was only a rare corner case in the old register allocator, but in the new
allocator this sequence is seen very often leading to code bloat of +50% for
some real-world functions.
This is the reason why the command line option -mstrict-X has been added to the
AVR backend, see PR46278.
This option denies fake *(X+const) addressing but leads to the mentioned spills
from register allocator and to code even worse as compared to without setting
-mstrict-X, i.e. register allocator sabotages a smart usage of the address
registers.
All I see is that reload1.c:alter_reg() generates the spill because
ira_conflicts_p is true.
With the option -morder1 turn on (affects ADJUST_REG_ALLOC_ORDER) there is
still a frame set up even though never accessed.
Can anyone give me some advice how to proceed with this issue?
Can be said if this is a target issue or IRA/reload flaw?
FYI, you find attached the IRA dump as generated with the above command line
Thanks for any hints!
Johann
GCC configured with:
--target=avr --disable-nls --disable-shared --enable-languages=c,c++
--with-dwarf2 --disable-lto --enable-checking=yes,rtl --enable-doc
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: in.c.192r.ira
URL: <https://gcc.gnu.org/pipermail/gcc/attachments/20111025/7abbce47/attachment.ksh>
More information about the Gcc
mailing list