Reload inheritance fix
Bernd Schmidt
bernds@redhat.co.uk
Sat Sep 16 09:31:00 GMT 2000
Testing an sh-elf toolchain with a commercial C testsuite showed up a problem
with reload inheritance. Suppose you have a situation like this:
(set (pseudo A) (foo)
[...]
(set (pseudo B) (bar)
[...]
(... (use (pseudo B)) ... (REG_DEAD pseudo B))
[...]
(... (use pseudo A) ...)
(... (use pseudo A) ... (REG_DEAD pseudo A))
where pseudo B gets allocted to hard reg X, and pseudo A fails to get a hard
reg.
For the first insn, reload chooses to reload A into hard reg X, setting
spill_reg_store etc. accordingly. It gets replaced with
(set (reg X) (foo))
(set (mem some_stack_slot) (reg X))
When we reach the last insn, we see that we have inherited pseudo A, this
pseudo is dead here, and we had a spill in the first insn that stored the
pseudo into memory. Since we inherited the pseudo, we can delete the
old output reload, right?
Not quite. We did inherit pseudo A in the last insn, but we inherited the
input reload from the immediately preceding insn. The original output reload
should have been long forgotten, since register X is clobbered by the set of
pseudo B. This is recognized by forget_old_reloads_1, but for some reason
that function does not clear spill_reg_store. The patch below changes it
to do that, which fixes the problem.
Note: there's another place in reload which looks like it attempts to fix the
same problem:
/* If reg_reloaded_valid is not set for this register,
there might be a stale spill_reg_store lying around.
We must clear it, since otherwise emit_reload_insns
might delete the store. */
if (! TEST_HARD_REG_BIT (reg_reloaded_valid, regno))
spill_reg_store[regno] = NULL_RTX;
I have a feeling that this may be unnecessary with the patch below, but I
don't want to risk deleting it now.
Bernd
* reload1.c (forget_old_reloads_1): If a hard reg is stored, clear
its entry in spill_reg_store.
Index: reload1.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/reload1.c,v
retrieving revision 1.275
diff -u -p -r1.275 reload1.c
--- reload1.c 2000/09/08 02:44:11 1.275
+++ reload1.c 2000/09/16 16:21:14
@@ -4020,7 +4020,10 @@ forget_old_reloads_1 (x, ignored, data)
reload reg in the current instruction. */
if (n_reloads == 0
|| ! TEST_HARD_REG_BIT (reg_is_output_reload, regno + i))
- CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i);
+ {
+ CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i);
+ spill_reg_store[regno + i] = 0;
+ }
}
/* Since value of X has changed,
More information about the Gcc-patches
mailing list