This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
register elimination problem
- From: Roman Zippel <zippel at linux-m68k dot org>
- To: <gcc at gcc dot gnu dot org>
- Date: Sun, 16 Dec 2001 00:23:55 +0100 (CET)
- Subject: register elimination problem
Hi,
There are currently basically two ELIMINABLE_REGS variants:
1)
#define ELIMINABLE_REGS { \
{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
{ ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM }, \
{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM } }
2)
#define ELIMINABLE_REGS \
{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} \
The function reload1.c:update_eliminables() was written with the first
version in mind.
There can now be a problem with targets using the second version. It can
happen that the arg pointer can't be eliminated with the stack pointer,
but the frame pointer can. The result is that the frame pointer isn't
initialized, but arguments are accessed through it.
Currently I'm using the patch below, the idea behind it is if a certain
elimination isn't possible, the destination register can't be used as
destination for any other elimination and this means hard registers can't
be eliminated into this register (version 1) and pseudo register must be
eliminated into another register (version 2).
There is another solution possible by finding all possible new_from for
new_to and disable also all eliminations from new_from to ep->to, but I
don't know if the added complexity is necessary. I checked the usage of
ELIMINABLE_REGS and IMO the simple solution below is sufficient.
BTW during that check I found that arm uses the second version, but also
has a "{ ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM }", which seems to solve
above problem as well, but looks fragil.
Any hints what the correct solution for this should be?
bye, Roman
Index: gcc/reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.255.4.13
diff -u -r1.255.4.13 reload1.c
--- reload1.c 2001/11/19 22:04:30 1.255.4.13
+++ reload1.c 2001/12/15 14:21:10
@@ -3434,25 +3434,14 @@
for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
{
struct elim_table *op;
- register int new_to = -1;
if (! ep->can_eliminate && ep->can_eliminate_previous)
{
- /* Find the current elimination for ep->from, if there is a
- new one. */
- for (op = reg_eliminate;
- op < ®_eliminate[NUM_ELIMINABLE_REGS]; op++)
- if (op->from == ep->from && op->can_eliminate)
- {
- new_to = op->to;
- break;
- }
-
/* See if there is an elimination of NEW_TO -> EP->TO. If so,
disable it. */
for (op = reg_eliminate;
op < ®_eliminate[NUM_ELIMINABLE_REGS]; op++)
- if (op->from == new_to && op->to == ep->to)
+ if (op->to == ep->to)
op->can_eliminate = 0;
}
}