From 234ac9e894ec3c47c97bf0180ca2eddbe2baf89e Mon Sep 17 00:00:00 2001 From: amylaar Date: Fri, 13 May 2005 18:22:57 +0000 Subject: [PATCH] PR middle-end/20714: * optabs.c (no_conflict_data): New struct. (no_conflict_move_test): New function. (emit_no_conflict_block): Use it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@99674 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 +++++++ gcc/optabs.c | 59 +++++++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 755db83..2c4c492 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2005-05-13 J"orn Rennecke + + 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 * doc/invoke.texi (Debugging Options): Option diff --git a/gcc/optabs.c b/gcc/optabs.c index 2955f7b..d3c4934 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -2943,6 +2943,39 @@ emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code) 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 word at a time. @@ -2988,8 +3021,8 @@ emit_no_conflict_block (rtx insns, rtx target, rtx op0, rtx op1, rtx equiv) these from the list. */ for (insn = insns; insn; insn = next) { - rtx set = 0, note; - int i; + rtx note; + struct no_conflict_data data; next = NEXT_INSN (insn); @@ -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) remove_note (insn, note); - if (GET_CODE (PATTERN (insn)) == SET || GET_CODE (PATTERN (insn)) == USE - || GET_CODE (PATTERN (insn)) == CLOBBER) - set = PATTERN (insn); - else if (GET_CODE (PATTERN (insn)) == PARALLEL) - { - for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) - 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))) + data.target = target; + data.first = insns; + data.insn = insn; + data.must_stay = 0; + note_stores (PATTERN (insn), no_conflict_move_test, &data); + if (! data.must_stay) { if (PREV_INSN (insn)) NEXT_INSN (PREV_INSN (insn)) = next; -- 2.7.4