[PATCH][PR target/63347][P3 Regression] Fix SCHED_GROUP_P handling in haifa-sched.c
Jeff Law
law@redhat.com
Wed Feb 11 23:29:00 GMT 2015
PR 63347 is a case where we can end up scheduling an insn into the
middle of a scheduling group.
Basically given two consecutive insns A & B, if B has SCHED_GROUP_P set,
then it must always be immediately after A.
The problem we ran into in this PR was that there was a cost to issue B,
so it got delayed several cycles. While B was delayed an earlier,
unrelated insn Z which had been delayed earlier became ready and issued.
The result being A Z B which ultimately led to incorrect code generation.
The fix is actually quite simple. In prune_ready_list, we queue insns
that have had their dependencies satisfied, but have a cost (say for
example, they're waiting for a functional unit to become available). We
want to queue based on that cost, with one exception. If the insn to be
queued is part of a scheduling group, then we want to queue it with cost 1.
That ensures that on each cycle, any SCHED_GROUP_P insn that has its
dependencies satisfied is in the ready list. Once we do that,
everything is in place to assure that nothing issues until after the
SCHED_GROUP_P insn issues.
Bootstrapped and regression tested on x86_64-unknown-linux-gnu. Also
verified the testcase works correctly on m68k-unknown-linux. Installed
on the trunk.
-------------- next part --------------
commit 07e421b3fbc2d29c9636200906c3edf3cbd33499
Author: Jeff Law <law@redhat.com>
Date: Wed Feb 11 16:19:05 2015 -0700
PR target/63347
* haifa-sched.c (prune_ready_list): If we have a SCHED_GROUP_P insn
that needs to be queued, just queue it for a single cycle.
PR target/63347
* gcc.target/m68k/pr63347.c: New test.
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d895209..c9ac045 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2015-02-11 Jeff Law <law@redhat.com>
+
+ PR target/63347
+ * haifa-sched.c (prune_ready_list): If we have a SCHED_GROUP_P insn
+ that needs to be queued, just queue it for a single cycle.
+
2015-02-11 Jan Hubicka <hubicka@ucw.cz>
* ipa.c (symbol_table::remove_unreachable_nodes): Avoid releasing
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 75d2421..64c8c9c1 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -6291,7 +6291,15 @@ prune_ready_list (state_t temp_state, bool first_cycle_insn_p,
if (SCHED_GROUP_P (insn) && cost > min_cost_group)
min_cost_group = cost;
ready_remove (&ready, i);
- queue_insn (insn, cost, reason);
+ /* Normally we'd want to queue INSN for COST cycles. However,
+ if SCHED_GROUP_P is set, then we must ensure that nothing
+ else comes between INSN and its predecessor. If there is
+ some other insn ready to fire on the next cycle, then that
+ invariant would be broken.
+
+ So when SCHED_GROUP_P is set, just queue this insn for a
+ single cycle. */
+ queue_insn (insn, SCHED_GROUP_P (insn) ? 1 : cost, reason);
if (i + 1 < n)
break;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c62cc23..ee5be51 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2015-02-11 Jeff Law <law@redhat.com>
+
+ PR target/63347
+ * gcc.target/m68k/pr63347.c: New test.
+
2015-02-11 Marek Polacek <polacek@redhat.com>
* g++.dg/ubsan/shift-1.C: New test.
diff --git a/gcc/testsuite/gcc.target/m68k/pr63347.c b/gcc/testsuite/gcc.target/m68k/pr63347.c
new file mode 100644
index 0000000..1d23e9a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/pr63347.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcpu=5208" } */
+
+#include <stdlib.h>
+
+void __attribute__ ((noinline))
+oof()
+{
+ asm volatile ("" ::: "memory");
+}
+int print_info(unsigned int *ip_addr)
+{
+ int invalid = 0;
+
+ if (ip_addr) {
+ unsigned int haddr = *ip_addr;
+ oof("stuff");
+ if (0x0 == haddr) {
+ invalid = 1;
+ }
+ oof("stuff2");
+ } else {
+ invalid = 1;
+ }
+
+ return invalid;
+}
+
+int main(int argc, char *argv[])
+{
+ unsigned int myaddr;
+ int ret;
+
+ myaddr = 0x0;
+ ret = print_info(&myaddr);
+ if (!ret)
+ abort ();
+
+ myaddr = 0x01020304;
+ ret = print_info(&myaddr);
+ if (ret)
+ abort ();
+ exit (0);
+}
+
+
More information about the Gcc-patches
mailing list