Commit 326a31e9 by J"orn Rennecke Committed by Joern Rennecke

re PR middle-end/20714 (emit_no_conflict_block does invalid reordering)

	PR middle-end/20714:
	* optabs.c (no_conflict_data): New struct.
	(no_conflict_move_test): New function.
	(emit_no_conflict_block): Use it.

From-SVN: r99674
parent 223dcf1c
2005-05-13 J"orn Rennecke <joern.rennecke@st.com>
PR middle-end/20714:
* optabs.c (no_conflict_data): New struct.
(no_conflict_move_test): New function.
(emit_no_conflict_block): Use it.
2005-05-13 Adam Nemet <anemet@lnxw.com> 2005-05-13 Adam Nemet <anemet@lnxw.com>
* doc/invoke.texi (Debugging Options): Option * doc/invoke.texi (Debugging Options): Option
......
...@@ -2943,6 +2943,39 @@ emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code) ...@@ -2943,6 +2943,39 @@ emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
emit_move_insn (target, temp); emit_move_insn (target, temp);
} }
struct no_conflict_data
{
rtx target, first, insn;
bool must_stay;
};
/* Called via note_stores by emit_no_conflict_block. Set P->must_stay
if the currently examined clobber / store has to stay in the list of
insns that constitute the actual no_conflict block. */
static void
no_conflict_move_test (rtx dest, rtx set, void *p0)
{
struct no_conflict_data *p= p0;
/* If this inns directly contributes to setting the target, it must stay. */
if (reg_overlap_mentioned_p (p->target, dest))
p->must_stay = true;
/* If we haven't committed to keeping any other insns in the list yet,
there is nothing more to check. */
else if (p->insn == p->first)
return;
/* If this insn sets / clobbers a register that feeds one of the insns
already in the list, this insn has to stay too. */
else if (reg_mentioned_p (dest, PATTERN (p->first))
|| reg_used_between_p (dest, p->first, p->insn)
/* Likewise if this insn depends on a register set by a previous
insn in the list. */
|| (GET_CODE (set) == SET
&& (modified_in_p (SET_SRC (set), p->first)
|| modified_between_p (SET_SRC (set), p->first, p->insn))))
p->must_stay = true;
}
/* Emit code to perform a series of operations on a multi-word quantity, one /* Emit code to perform a series of operations on a multi-word quantity, one
word at a time. word at a time.
...@@ -2988,8 +3021,8 @@ emit_no_conflict_block (rtx insns, rtx target, rtx op0, rtx op1, rtx equiv) ...@@ -2988,8 +3021,8 @@ emit_no_conflict_block (rtx insns, rtx target, rtx op0, rtx op1, rtx equiv)
these from the list. */ these from the list. */
for (insn = insns; insn; insn = next) for (insn = insns; insn; insn = next)
{ {
rtx set = 0, note; rtx note;
int i; struct no_conflict_data data;
next = NEXT_INSN (insn); next = NEXT_INSN (insn);
...@@ -3000,22 +3033,12 @@ emit_no_conflict_block (rtx insns, rtx target, rtx op0, rtx op1, rtx equiv) ...@@ -3000,22 +3033,12 @@ emit_no_conflict_block (rtx insns, rtx target, rtx op0, rtx op1, rtx equiv)
if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL) if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
remove_note (insn, note); remove_note (insn, note);
if (GET_CODE (PATTERN (insn)) == SET || GET_CODE (PATTERN (insn)) == USE data.target = target;
|| GET_CODE (PATTERN (insn)) == CLOBBER) data.first = insns;
set = PATTERN (insn); data.insn = insn;
else if (GET_CODE (PATTERN (insn)) == PARALLEL) data.must_stay = 0;
{ note_stores (PATTERN (insn), no_conflict_move_test, &data);
for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) if (! data.must_stay)
if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
{
set = XVECEXP (PATTERN (insn), 0, i);
break;
}
}
gcc_assert (set);
if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
{ {
if (PREV_INSN (insn)) if (PREV_INSN (insn))
NEXT_INSN (PREV_INSN (insn)) = next; NEXT_INSN (PREV_INSN (insn)) = next;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment