aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfglayout.c
diff options
context:
space:
mode:
authorZdenek Dvorak <dvorakz@suse.cz>2007-07-17 05:56:40 +0200
committerZdenek Dvorak <rakdver@gcc.gnu.org>2007-07-17 03:56:40 +0000
commit9f2e9ac43b09713711d3f358a2ab4dbb86a925bb (patch)
tree4a7695fc9b2d11cc77b1801a9f85ca70199d8db4 /gcc/cfglayout.c
parent02634bb2873d57f5beda6c0f1633b8bfdbc08ffa (diff)
downloadgcc-9f2e9ac43b09713711d3f358a2ab4dbb86a925bb.zip
gcc-9f2e9ac43b09713711d3f358a2ab4dbb86a925bb.tar.gz
gcc-9f2e9ac43b09713711d3f358a2ab4dbb86a925bb.tar.bz2
re PR rtl-optimization/32773 (SH: ICE in create_pre_exit, at mode-switching.c:223)
PR rtl-optimization/32773 * cfglayout.c (force_one_exit_fallthru): New function. (cfg_layout_finalize): Use it. * gcc.dg/pr32773.c: New test. From-SVN: r126700
Diffstat (limited to 'gcc/cfglayout.c')
-rw-r--r--gcc/cfglayout.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c
index be4b087..e989344 100644
--- a/gcc/cfglayout.c
+++ b/gcc/cfglayout.c
@@ -963,6 +963,56 @@ fixup_fallthru_exit_predecessor (void)
bb->aux = NULL;
}
}
+
+/* In case there are more than one fallthru predecessors of exit, force that
+ there is only one. */
+
+static void
+force_one_exit_fallthru (void)
+{
+ edge e, predecessor = NULL;
+ bool more = false;
+ edge_iterator ei;
+ basic_block forwarder, bb;
+
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
+ if (e->flags & EDGE_FALLTHRU)
+ {
+ if (predecessor == NULL)
+ predecessor = e;
+ else
+ {
+ more = true;
+ break;
+ }
+ }
+
+ if (!more)
+ return;
+
+ /* Exit has several fallthru predecessors. Create a forwarder block for
+ them. */
+ forwarder = split_edge (predecessor);
+ for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); )
+ {
+ if (e->src == forwarder
+ || !(e->flags & EDGE_FALLTHRU))
+ ei_next (&ei);
+ else
+ redirect_edge_and_branch_force (e, forwarder);
+ }
+
+ /* Fix up the chain of blocks -- make FORWARDER immediately preceed the
+ exit block. */
+ FOR_EACH_BB (bb)
+ {
+ if (bb->aux == NULL && bb != forwarder)
+ {
+ bb->aux = forwarder;
+ break;
+ }
+ }
+}
/* Return true in case it is possible to duplicate the basic block BB. */
@@ -1178,6 +1228,7 @@ cfg_layout_finalize (void)
#ifdef ENABLE_CHECKING
verify_flow_info ();
#endif
+ force_one_exit_fallthru ();
rtl_register_cfg_hooks ();
if (reload_completed
#ifdef HAVE_epilogue