This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
fix reload failures on alpha and ppc64
- From: Richard Henderson <rth at twiddle dot net>
- To: Bernd Schmidt <bernd dot schmidt at analog dot com>, gcc-patches at gcc dot gnu dot org
- Date: Fri, 17 Jun 2005 01:56:46 -0700
- Subject: fix reload failures on alpha and ppc64
Last night's runs failed with
/home/rth/work/gcc/src-cron/gcc/fortran/intrinsic.c:2044: error: insn does not
+satisfy its constraints:
(insn 7653 3246 8065 0 /home/rth/work/gcc/src-cron/gcc/fortran/intrinsic.c:1410
+(set (reg/f:SI 1429)
(high:SI (symbol_ref/f:SI ("*.LC24") [flags 0x2] <string_cst
+0xf7abbd40>))) 373 {elf_high} (nil)
(expr_list:REG_EQUIV (high:SI (symbol_ref/f:SI ("*.LC24") [flags 0x2]
+<string_cst 0xf7abbd40>))
(nil)))
and
/home/rth/work/gcc/src-cron/libjava/gnu/gcj/io/shs.cc:183: error: insn does not
+satisfy its constraints:
(insn 4254 3812 4257 2 /home/rth/work/gcc/src-cron/libjava/gnu/gcj/io/shs.cc:153+(set (reg:SI 860)
(const_int 1518469120 [0x5a820000])) 239 {*movsi} (nil)
(expr_list:REG_EQUIV (const_int 1518469120 [0x5a820000])
(nil)))
Note in both cases we have a pseudo register present after reload.
Oops.
The problem appears to be that (1) we lose track of the initialization
insn of these REG_EQUIVs, and (2) there's a mismatch between the place
that decides when we're going to skip reloading an insn, and the place
that decides when we're going to delete an insn. The former, at
/* Skip insns that only set an equivalence. */
if (set && REG_P (SET_DEST (set))
&& reg_renumber[REGNO (SET_DEST (set))] < 0
&& reg_equiv_constant[REGNO (SET_DEST (set))])
continue;
in calculate_needs_all_insns, and the later at
/* If a pseudo has no hard reg, delete the insns that made the equivalence.
If that insn didn't set the register (i.e., it copied the register to
memory), just delete that insn instead of the equivalencing insn plus
anything now dead. If we call delete_dead_insn on that insn, we may
delete the insn that actually sets the register if the register dies
there and that is incorrect. */
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
{
if (reg_renumber[i] < 0 && reg_equiv_init[i] != 0)
{
rtx list;
for (list = reg_equiv_init[i]; list; list = XEXP (list, 1))
in reload.
This only tries to address point 1 -- losing track of the initialization
insn. Which should be enough to suppress the observable failure; I'll
let Bernd figure out what he wants to do about the mismatch when he gets
back next week.
The problem appears to be a cut-and-paste error from the asm case just
above, which does delete the equivalence insn. In this case we're moving
it, so we should move the initialization insn too.
This has been spot-checked against the shs.cc test case on alpha. I'm
running full tests on alpha and ppc64 overnight.
r~
* local-alloc.c (update_equiv_regs): Update reg_equiv_init
properly when moving an initialization insn.
Index: local-alloc.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/local-alloc.c,v
retrieving revision 1.150
diff -u -p -d -r1.150 local-alloc.c
--- local-alloc.c 16 Jun 2005 10:33:14 -0000 1.150
+++ local-alloc.c 17 Jun 2005 08:44:21 -0000
@@ -1177,7 +1177,8 @@ update_equiv_regs (void)
info. */
SET_REGNO_REG_SET (&cleared_regs, regno);
clear_regnos++;
- reg_equiv_init[regno] = NULL_RTX;
+ reg_equiv_init[regno]
+ = gen_rtx_INSN_LIST (VOIDmode, new_insn, NULL_RTX);
}
}
}