This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: RFA: Fix PR middle-end/20714
- From: Joern RENNECKE <joern dot rennecke at st dot com>
- To: Richard Henderson <rth at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 13 May 2005 14:46:41 +0100
- Subject: Re: RFA: Fix PR middle-end/20714
- References: <4256D3DE.2080905@st.com> <20050513033404.GB9104@redhat.com>
Richard Henderson wrote:
At minimum I'd like "insns" renamed to "first" or something. My
eyes don't seem to distinguish insn/insns well. Also, break this
condition up.
Otherwise it looks like an ok approach.
r~
I have appended an updated patch. Testing now on i686-pc-linux-gnu
native and
X sh-elf.
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.
Index: optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.278
diff -p -r1.278 optabs.c
*** optabs.c 10 May 2005 16:24:41 -0000 1.278
--- optabs.c 13 May 2005 13:41:57 -0000
*************** emit_unop_insn (int icode, rtx target, r
*** 2943,2948 ****
--- 2943,2981 ----
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.
*************** emit_no_conflict_block (rtx insns, rtx t
*** 2988,2995 ****
these from the list. */
for (insn = insns; insn; insn = next)
{
! rtx set = 0, note;
! int i;
next = NEXT_INSN (insn);
--- 3021,3028 ----
these from the list. */
for (insn = insns; insn; insn = next)
{
! rtx note;
! struct no_conflict_data data;
next = NEXT_INSN (insn);
*************** emit_no_conflict_block (rtx insns, rtx t
*** 3000,3021 ****
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)))
{
if (PREV_INSN (insn))
NEXT_INSN (PREV_INSN (insn)) = next;
--- 3033,3044 ----
if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
remove_note (insn, note);
! 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;