re PR rtl-optimization/32773 (SH: ICE in create_pre_exit, at mode-switching.c:223)
authorZdenek Dvorak <dvorakz@suse.cz>
Tue, 17 Jul 2007 03:56:40 +0000 (05:56 +0200)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Tue, 17 Jul 2007 03:56:40 +0000 (03:56 +0000)
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

gcc/ChangeLog
gcc/cfglayout.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr32773.c [new file with mode: 0644]

index ab57f35fa516807b119238850ac398c4bec2d4a0..7b7dee07815fb9481c9b68c990f4457da35dffe4 100644 (file)
@@ -1,3 +1,9 @@
+2007-07-17  Zdenek Dvorak  <dvorakz@suse.cz>
+
+       PR rtl-optimization/32773
+       * cfglayout.c (force_one_exit_fallthru): New function.
+       (cfg_layout_finalize): Use it.
+
 2007-07-16  Richard Guenther  <rguenther@suse.de>
            Uros Bizjak  <ubizjak@gmail.com>
 
index be4b08767b9fa625a3a03919d01f4e62ff86011a..e989344cd801195096e7254878ff7012eb9d9f98 100644 (file)
@@ -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;
+       }
+    }
+}
 \f
 /* 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
index a645d92a0e40c7353b7f85f2aaf837d2cf7988db..cb178678f89e5abf882468fa2d7625532f2c966f 100644 (file)
@@ -1,3 +1,8 @@
+2007-07-17  Zdenek Dvorak  <dvorakz@suse.cz>
+
+       PR rtl-optimization/32773
+       * gcc.dg/pr32773.c: New test.
+
 2007-07-16  Andrew Pinski  <andrew_pinski@playstation.sony.com>
 
        * gcc.target/spu/intrinsics-1.c: Use dg-message to
diff --git a/gcc/testsuite/gcc.dg/pr32773.c b/gcc/testsuite/gcc.dg/pr32773.c
new file mode 100644 (file)
index 0000000..ca5dd53
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fprofile-use" } */
+/* { dg-options "-O -m4 -fprofile-use" { target sh-*-* } } */
+
+void foo (int *p)
+{
+  if (p)
+    *p = 0;
+} /* { dg-message "note: \[^\n\]*execution counts estimated" } */
+
+/* { dg-final { cleanup-coverage-files } } */