This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RFA: Fix for PR
- From: Nick Clifton <nickc at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 30 Jan 2006 12:24:27 +0000
- Subject: RFA: Fix for PR
Hi Guys,
Attached is a patch that fixes PR 27346, a scheduling bug on the 3.4
branch which is exposed for the v850 toolchain. The problem is that
when add_branch_dependences() is scanning backwards from the end of
a basic block to find the first instruction that it can safely
schedule it does not take into account that for cc0 targets there can
be multiple cc0 setter/consumer pairs and that none of these pairs
should be split up.
The patch fixes the problem by extending the search backwards until
the first cc0 setter in the basic block is found and marking it, and
all instructions following, as CANT_MOVE.
Tested with no regressions on a v850-elf and a i386-pc-linux-gnu
toolchain.
Please may I apply this patch to the 3.4 branch ?
Cheers
Nick
gcc/ChangeLog
2006-01-10 Nick Clifton <nickc@redhat.com>
PR 27346
* sched-rgn.c (add_branch_dependences): For cc0 targets extend
the dependencies inside a block back to the very first cc0 setter
in the block.
Index: sched-rgn.c
===================================================================
--- sched-rgn.c (revision 109541)
+++ sched-rgn.c (working copy)
@@ -2078,6 +2078,42 @@
insn = PREV_INSN (insn);
}
+#ifdef HAVE_cc0
+ /* There may be other cc0 setters earlier on in this block.
+ Look for them and include them in the set not to be disturbed. */
+ if (insn != head && last != NULL_RTX)
+ {
+ rtx earlier_cc0_setter = NULL_RTX;
+
+ for (insn = last; insn != NULL_RTX && insn != head;)
+ {
+ insn = prev_nonnote_insn (insn);
+ if (sets_cc0_p (insn))
+ earlier_cc0_setter = insn;
+ }
+
+ if (earlier_cc0_setter != NULL_RTX)
+ {
+ insn = last;
+ do
+ {
+ insn = prev_nonnote_insn (insn);
+
+ if (last != 0 && ! find_insn_list (insn, LOG_LINKS (last)))
+ {
+ add_dependence (last, insn, REG_DEP_ANTI);
+ INSN_REF_COUNT (insn)++;
+ }
+
+ CANT_MOVE (insn) = 1;
+
+ last = insn;
+ }
+ while (insn != earlier_cc0_setter);
+ }
+ }
+#endif
+
/* Make sure these insns are scheduled last in their block. */
insn = last;
if (insn != 0)