jump.c (delete_prior_computation): New function, broken out of delete_computation.

* jump.c (delete_prior_computation): New function, broken
	out of delete_computation.  Check for side effects with
	side_effects_p instead of FIND_REG_INC_NOTE.  Handle
	multi-word hard registers.
	(delete_computation): Use it.  Check for side effects with
	side_effects_p instead of FIND_REG_INC_NOTE.  Synthesize a
	missing REG_DEAD note for a register which is both set and
	used by an insn.

From-SVN: r28558
This commit is contained in:
John Wehle 1999-08-06 20:55:42 +00:00 committed by John Wehle
parent 3fabe028e0
commit cfe2d2e7f5
2 changed files with 133 additions and 58 deletions

View File

@ -1,3 +1,14 @@
Fri Aug 6 16:53:55 EDT 1999 John Wehle (john@feith.com)
* jump.c (delete_prior_computation): New function, broken
out of delete_computation. Check for side effects with
side_effects_p instead of FIND_REG_INC_NOTE. Handle
multi-word hard registers.
(delete_computation): Use it. Check for side effects with
side_effects_p instead of FIND_REG_INC_NOTE. Synthesize a
missing REG_DEAD note for a register which is both set and
used by an insn.
Fri Aug 6 11:05:29 1999 Jeffrey A Law (law@cygnus.com)
* elf.h (TEXT_SPACE_P, FUNCTION_NAME_P): Delete.

View File

@ -3811,6 +3811,112 @@ delete_jump (insn)
delete_computation (insn);
}
/* Recursively delete prior insns that compute the value (used only by INSN
which the caller is deleting) stored in the register mentioned by NOTE
which is a REG_DEAD note associated with INSN. */
static void
delete_prior_computation (note, insn)
rtx note;
rtx insn;
{
rtx our_prev;
rtx reg = XEXP (note, 0);
for (our_prev = prev_nonnote_insn (insn);
our_prev && GET_CODE (our_prev) == INSN;
our_prev = prev_nonnote_insn (our_prev))
{
rtx pat = PATTERN (our_prev);
/* If we reach a SEQUENCE, it is too complex to try to
do anything with it, so give up. */
if (GET_CODE (pat) == SEQUENCE)
break;
if (GET_CODE (pat) == USE
&& GET_CODE (XEXP (pat, 0)) == INSN)
/* reorg creates USEs that look like this. We leave them
alone because reorg needs them for its own purposes. */
break;
if (reg_set_p (reg, pat))
{
if (side_effects_p (pat))
break;
if (GET_CODE (pat) == PARALLEL)
{
/* If we find a SET of something else, we can't
delete the insn. */
int i;
for (i = 0; i < XVECLEN (pat, 0); i++)
{
rtx part = XVECEXP (pat, 0, i);
if (GET_CODE (part) == SET
&& SET_DEST (part) != reg)
break;
}
if (i == XVECLEN (pat, 0))
delete_computation (our_prev);
}
else if (GET_CODE (pat) == SET
&& GET_CODE (SET_DEST (pat)) == REG)
{
int dest_regno = REGNO (SET_DEST (pat));
int dest_endregno
= dest_regno + (dest_regno < FIRST_PSEUDO_REGISTER
? HARD_REGNO_NREGS (dest_regno,
GET_MODE (SET_DEST (pat))) : 1);
int regno = REGNO (reg);
int endregno = regno + (regno < FIRST_PSEUDO_REGISTER
? HARD_REGNO_NREGS (regno, GET_MODE (reg)) : 1);
if (dest_regno >= regno
&& dest_endregno <= endregno)
delete_computation (our_prev);
/* We may have a multi-word hard register and some, but not
all, of the words of the register are needed in subsequent
insns. Write REG_UNUSED notes for those parts that were not
needed. */
else if (dest_regno <= regno
&& dest_endregno >= endregno
&& ! find_regno_note (our_prev, REG_UNUSED, REGNO(reg)))
{
int i;
REG_NOTES (our_prev)
= gen_rtx_EXPR_LIST (REG_UNUSED, reg, REG_NOTES (our_prev));
for (i = dest_regno; i < dest_endregno; i++)
if (! find_regno_note (our_prev, REG_UNUSED, i))
break;
if (i == dest_endregno)
delete_computation (our_prev);
}
}
break;
}
/* If PAT references the register that dies here, it is an
additional use. Hence any prior SET isn't dead. However, this
insn becomes the new place for the REG_DEAD note. */
if (reg_overlap_mentioned_p (reg, pat))
{
XEXP (note, 1) = REG_NOTES (our_prev);
REG_NOTES (our_prev) = note;
break;
}
}
}
/* Delete INSN and recursively delete insns that compute values used only
by INSN. This uses the REG_DEAD notes computed during flow analysis.
If we are running before flow.c, we need do nothing since flow.c will
@ -3829,6 +3935,7 @@ delete_computation (insn)
rtx insn;
{
rtx note, next;
rtx set;
#ifdef HAVE_cc0
if (reg_referenced_p (cc0_rtx, PATTERN (insn)))
@ -3844,7 +3951,7 @@ delete_computation (insn)
&& sets_cc0_p (PATTERN (prev)))
{
if (sets_cc0_p (PATTERN (prev)) > 0
&& !FIND_REG_INC_NOTE (prev, NULL_RTX))
&& ! side_effects_p (PATTERN (prev)))
delete_computation (prev);
else
/* Otherwise, show that cc0 won't be used. */
@ -3865,10 +3972,10 @@ delete_computation (insn)
}
#endif
set = single_set (insn);
for (note = REG_NOTES (insn); note; note = next)
{
rtx our_prev;
next = XEXP (note, 1);
if (REG_NOTE_KIND (note) != REG_DEAD
@ -3876,63 +3983,20 @@ delete_computation (insn)
|| GET_CODE (XEXP (note, 0)) != REG)
continue;
for (our_prev = prev_nonnote_insn (insn);
our_prev && GET_CODE (our_prev) == INSN;
our_prev = prev_nonnote_insn (our_prev))
{
/* If we reach a SEQUENCE, it is too complex to try to
do anything with it, so give up. */
if (GET_CODE (PATTERN (our_prev)) == SEQUENCE)
break;
if (set && reg_overlap_mentioned_p (SET_DEST (set), XEXP (note, 0)))
set = NULL_RTX;
if (GET_CODE (PATTERN (our_prev)) == USE
&& GET_CODE (XEXP (PATTERN (our_prev), 0)) == INSN)
/* reorg creates USEs that look like this. We leave them
alone because reorg needs them for its own purposes. */
break;
delete_prior_computation (note, insn);
}
if (reg_set_p (XEXP (note, 0), PATTERN (our_prev)))
{
if (FIND_REG_INC_NOTE (our_prev, NULL_RTX))
break;
if (GET_CODE (PATTERN (our_prev)) == PARALLEL)
{
/* If we find a SET of something else, we can't
delete the insn. */
int i;
for (i = 0; i < XVECLEN (PATTERN (our_prev), 0); i++)
{
rtx part = XVECEXP (PATTERN (our_prev), 0, i);
if (GET_CODE (part) == SET
&& SET_DEST (part) != XEXP (note, 0))
break;
}
if (i == XVECLEN (PATTERN (our_prev), 0))
delete_computation (our_prev);
}
else if (GET_CODE (PATTERN (our_prev)) == SET
&& SET_DEST (PATTERN (our_prev)) == XEXP (note, 0))
delete_computation (our_prev);
break;
}
/* If OUR_PREV references the register that dies here, it is an
additional use. Hence any prior SET isn't dead. However, this
insn becomes the new place for the REG_DEAD note. */
if (reg_overlap_mentioned_p (XEXP (note, 0),
PATTERN (our_prev)))
{
XEXP (note, 1) = REG_NOTES (our_prev);
REG_NOTES (our_prev) = note;
break;
}
}
/* The REG_DEAD note may have been omitted for a register
which is both set and used by the insn. */
if (set
&& GET_CODE (SET_DEST (set)) == REG
&& reg_mentioned_p (SET_DEST (set), SET_SRC (set)))
{
note = gen_rtx_EXPR_LIST (REG_DEAD, SET_DEST (set), NULL_RTX);
delete_prior_computation (note, insn);
}
delete_insn (insn);