fix c/5290: Miscompilation of GDB on i386
Richard Henderson
rth@redhat.com
Thu Jan 10 19:24:00 GMT 2002
The ugliness here stems from emitting one output reload insn, deleting it,
emitting a second reload insn, then deleting the first reload insn a second
time. The duplicate deletion scrogs the insn chain and we lose stuff.
Bootstrapped and checked on alphaev6 and i686 linux.
r~
* cfgrtl.c (delete_insn): Assert insn hasn't been deleted yet.
* reload1.c (delete_output_reload): Zap spill_reg_store. Take
care not to delete instructions twice.
Index: cfgrtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgrtl.c,v
retrieving revision 1.25
diff -c -p -d -r1.25 cfgrtl.c
*** cfgrtl.c 2002/01/10 20:37:42 1.25
--- cfgrtl.c 2002/01/11 02:43:15
*************** delete_insn (insn)
*** 135,140 ****
--- 135,143 ----
if (really_delete)
{
+ /* If this insn has already been deleted, something is very wrong. */
+ if (INSN_DELETED_P (insn))
+ abort ();
remove_insn (insn);
INSN_DELETED_P (insn) = 1;
}
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.319
diff -c -p -d -r1.319 reload1.c
*** reload1.c 2002/01/10 00:56:54 1.319
--- reload1.c 2002/01/11 02:43:15
*************** gen_reload (out, in, opnum, type)
*** 7537,7545 ****
return last ? NEXT_INSN (last) : get_insns ();
}
! /* Delete a previously made output-reload
! whose result we now believe is not needed.
! First we double-check.
INSN is the insn now being processed.
LAST_RELOAD_REG is the hard register number for which we want to delete
--- 7537,7544 ----
return last ? NEXT_INSN (last) : get_insns ();
}
! /* Delete a previously made output-reload whose result we now believe
! is not needed. First we double-check.
INSN is the insn now being processed.
LAST_RELOAD_REG is the hard register number for which we want to delete
*************** delete_output_reload (insn, j, last_relo
*** 7633,7647 ****
}
}
/* The caller has already checked that REG dies or is set in INSN.
! It has also checked that we are optimizing, and thus some inaccurancies
! in the debugging information are acceptable.
! So we could just delete output_reload_insn.
! But in some cases we can improve the debugging information without
! sacrificing optimization - maybe even improving the code:
! See if the pseudo reg has been completely replaced
! with reload regs. If so, delete the store insn
! and forget we had a stack slot for the pseudo. */
if (rld[j].out != rld[j].in
&& REG_N_DEATHS (REGNO (reg)) == 1
&& REG_N_SETS (REGNO (reg)) == 1
--- 7632,7652 ----
}
}
+ /* We will be deleting the insn. Remove the spill reg information. */
+ for (k = HARD_REGNO_NREGS (last_reload_reg, GET_MODE (reg)); k-- > 0; )
+ {
+ spill_reg_store[last_reload_reg + k] = 0;
+ spill_reg_stored_to[last_reload_reg + k] = 0;
+ }
+
/* The caller has already checked that REG dies or is set in INSN.
! It has also checked that we are optimizing, and thus some
! inaccurancies in the debugging information are acceptable.
! So we could just delete output_reload_insn. But in some cases
! we can improve the debugging information without sacrificing
! optimization - maybe even improving the code: See if the pseudo
! reg has been completely replaced with reload regs. If so, delete
! the store insn and forget we had a stack slot for the pseudo. */
if (rld[j].out != rld[j].in
&& REG_N_DEATHS (REGNO (reg)) == 1
&& REG_N_SETS (REGNO (reg)) == 1
*************** delete_output_reload (insn, j, last_relo
*** 7650,7660 ****
{
rtx i2;
! /* We know that it was used only between here
! and the beginning of the current basic block.
! (We also know that the last use before INSN was
! the output reload we are thinking of deleting, but never mind that.)
! Search that range; see if any ref remains. */
for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2))
{
rtx set = single_set (i2);
--- 7655,7664 ----
{
rtx i2;
! /* We know that it was used only between here and the beginning of
! the current basic block. (We also know that the last use before
! INSN was the output reload we are thinking of deleting, but never
! mind that.) Search that range; see if any ref remains. */
for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2))
{
rtx set = single_set (i2);
*************** delete_output_reload (insn, j, last_relo
*** 7677,7683 ****
}
}
! /* Delete the now-dead stores into this pseudo. */
for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2))
{
rtx set = single_set (i2);
--- 7681,7688 ----
}
}
! /* Delete the now-dead stores into this pseudo. Note that this
! loop also takes care of deleting output_reload_insn. */
for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2))
{
rtx set = single_set (i2);
*************** delete_output_reload (insn, j, last_relo
*** 7685,7692 ****
if (set != 0 && SET_DEST (set) == reg)
{
delete_address_reloads (i2, insn);
- /* This might be a basic block head,
- thus don't use delete_insn. */
delete_insn (i2);
}
if (GET_CODE (i2) == CODE_LABEL
--- 7690,7695 ----
*************** delete_output_reload (insn, j, last_relo
*** 7694,7707 ****
break;
}
! /* For the debugging info,
! say the pseudo lives in this reload reg. */
reg_renumber[REGNO (reg)] = REGNO (rld[j].reg_rtx);
alter_reg (REGNO (reg), -1);
}
! delete_address_reloads (output_reload_insn, insn);
! delete_insn (output_reload_insn);
!
}
/* We are going to delete DEAD_INSN. Recursively delete loads of
--- 7697,7711 ----
break;
}
! /* For the debugging info, say the pseudo lives in this reload reg. */
reg_renumber[REGNO (reg)] = REGNO (rld[j].reg_rtx);
alter_reg (REGNO (reg), -1);
}
! else
! {
! delete_address_reloads (output_reload_insn, insn);
! delete_insn (output_reload_insn);
! }
}
/* We are going to delete DEAD_INSN. Recursively delete loads of
More information about the Gcc-patches
mailing list