aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-microblaze/gcc/files/gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-microblaze/gcc/files/gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch')
-rw-r--r--recipes-microblaze/gcc/files/gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch110
1 files changed, 110 insertions, 0 deletions
diff --git a/recipes-microblaze/gcc/files/gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch b/recipes-microblaze/gcc/files/gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch
new file mode 100644
index 00000000..1cdc4029
--- /dev/null
+++ b/recipes-microblaze/gcc/files/gcc-Cherry-pick-mainline-patch-to-resolve-MB-k.patch
@@ -0,0 +1,110 @@
+Subject: Cherry-pick mainline patch to resolve MB kernel panic
+
+Cherry-pick backend optimization patch from gcc HEAD which 'resolves' a kernel
+panic for microblaze when compiled with -Os
+
+Upstream HEAD (soon to be gcc 4.9) does not exhibt this error any longer,
+and this patch when applied as a workaround on the 4.8 branch also hides the
+kernel panic resulting from incorrect branch-delay slot filling.
+
+ * tree-ssa-threadedge.c (thread_around_empty_block): Remove
+ checks for the number of predecessors and successors allowed.
+ * tree-ssa-threadupdate.c (mark_threaded_blocks): Ignore requests
+ which require copying a joiner block if there is a request which
+ is a subpath that requires no joiner block copying.
+
+Signed-off-by: David Holsgrove <david.holsgrove@xilinx.com>
+Upstream-Status: Backport
+---
+ gcc/tree-ssa-threadedge.c | 8 -------
+ gcc/tree-ssa-threadupdate.c | 49 ++++++++++++++++++++++++++++++++++++++-----
+ 2 files changed, 44 insertions(+), 13 deletions(-)
+
+diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
+index b31e961..ab58ae8 100644
+--- a/gcc/tree-ssa-threadedge.c
++++ b/gcc/tree-ssa-threadedge.c
+@@ -761,14 +761,6 @@ thread_around_empty_block (edge taken_edge,
+ gimple stmt;
+ tree cond;
+
+- /* This block must have a single predecessor (E->dest). */
+- if (!single_pred_p (bb))
+- return NULL;
+-
+- /* This block must have more than one successor. */
+- if (single_succ_p (bb))
+- return NULL;
+-
+ /* This block can have no PHI nodes. This is overly conservative. */
+ if (!gsi_end_p (gsi_start_phis (bb)))
+ return NULL;
+diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c
+index 0e4cbc9..cf8df8e 100644
+--- a/gcc/tree-ssa-threadupdate.c
++++ b/gcc/tree-ssa-threadupdate.c
+@@ -1146,17 +1146,56 @@ mark_threaded_blocks (bitmap threaded_blocks)
+ edge e;
+ edge_iterator ei;
+
++ /* It is possible to have jump threads in which one is a subpath
++ of the other. ie, (A, B), (B, C), (C, D) where B is a joiner
++ block and (B, C), (C, D) where no joiner block exists.
++
++ When this occurs ignore the jump thread request with the joiner
++ block. It's totally subsumed by the simpler jump thread request.
++
++ This results in less block copying, simpler CFGs. More improtantly,
++ when we duplicate the joiner block, B, in this case we will create
++ a new threading opportunity that we wouldn't be able to optimize
++ until the next jump threading iteration.
++
++ So first convert the jump thread requests which do not require a
++ joiner block. */
+ for (i = 0; i < threaded_edges.length (); i += 3)
+ {
+ edge e = threaded_edges[i];
+- edge *x = XNEWVEC (edge, 2);
+
+- e->aux = x;
+- THREAD_TARGET (e) = threaded_edges[i + 1];
+- THREAD_TARGET2 (e) = threaded_edges[i + 2];
+- bitmap_set_bit (tmp, e->dest->index);
++ if (threaded_edges[i + 2] == NULL)
++ {
++ edge *x = XNEWVEC (edge, 2);
++
++ e->aux = x;
++ THREAD_TARGET (e) = threaded_edges[i + 1];
++ THREAD_TARGET2 (e) = NULL;
++ bitmap_set_bit (tmp, e->dest->index);
++ }
+ }
+
++
++ /* Now iterate again, converting cases where we threaded through
++ a joiner block, but ignoring those where we have already
++ threaded through the joiner block. */
++ for (i = 0; i < threaded_edges.length (); i += 3)
++ {
++ edge e = threaded_edges[i];
++
++ if (threaded_edges[i + 2] != NULL
++ && threaded_edges[i + 1]->aux == NULL)
++ {
++ edge *x = XNEWVEC (edge, 2);
++
++ e->aux = x;
++ THREAD_TARGET (e) = threaded_edges[i + 1];
++ THREAD_TARGET2 (e) = threaded_edges[i + 2];
++ bitmap_set_bit (tmp, e->dest->index);
++ }
++ }
++
++
+ /* If optimizing for size, only thread through block if we don't have
+ to duplicate it or it's an otherwise empty redirection block. */
+ if (optimize_function_for_size_p (cfun))
+--
+1.7.9.5
+