]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/19484 (function pointer propagation fails for noreturn functions)
authorRichard Sandiford <rsandifo@redhat.com>
Sat, 22 Jan 2005 17:52:44 +0000 (17:52 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sat, 22 Jan 2005 17:52:44 +0000 (17:52 +0000)
PR tree-optimization/19484
* tree-cfg.c (remove_fallthru_edge): New function.
(cleanup_control_flow): Remove fallthru edges from calls that are
now known not to return.

From-SVN: r94070

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/20050122-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/compile/20050122-2.c [new file with mode: 0644]
gcc/tree-cfg.c

index 1a9d9e6cbb72f850d370ec5325f469654ffd10f3..69b5bc1ca453853e7628df1823146678ae01814d 100644 (file)
@@ -1,3 +1,10 @@
+2005-01-22  Richard Sandiford  <rsandifo@redhat.com>
+
+       PR tree-optimization/19484
+       * tree-cfg.c (remove_fallthru_edge): New function.
+       (cleanup_control_flow): Remove fallthru edges from calls that are
+       now known not to return.
+
 2005-01-20  Daniel Berlin  <dberlin@dberlin.org>
 
        Fix PR tree-optimization/19038
index 6b16fc8542e2fc0029d76283cdc428c3a3651cfe..c8930cbbf688bc03416340d04b21708156b5aec6 100644 (file)
@@ -1,3 +1,8 @@
+2005-01-22  Richard Sandiford  <rsandifo@redhat.com>
+
+       PR tree-optimization/19484
+       * gcc.c-torture/compile/20050122-[12].c: New tests.
+
 2005-01-22  Paul Brook  <paul@codesourcery.com>
 
        * gfortran.dg/implicit_2.f90: New test.
diff --git a/gcc/testsuite/gcc.c-torture/compile/20050122-1.c b/gcc/testsuite/gcc.c-torture/compile/20050122-1.c
new file mode 100644 (file)
index 0000000..a70907d
--- /dev/null
@@ -0,0 +1,12 @@
+/* From PR 19484.  */
+extern void foo (void) __attribute__((noreturn));
+int n;
+
+void
+g (void)
+{
+  void (*f) (void) = foo;
+  if (n)
+    f ();
+  n = 1;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/20050122-2.c b/gcc/testsuite/gcc.c-torture/compile/20050122-2.c
new file mode 100644 (file)
index 0000000..d73f624
--- /dev/null
@@ -0,0 +1,19 @@
+/* Related to PR 19484.  */
+extern void foo (void) __attribute__((noreturn));
+int n;
+
+void
+g (void)
+{
+  __label__ lab;
+  void h (void) { if (n == 2) goto lab; }
+  void (*f1) (void) = foo;
+  void (*f2) (void) = h;
+
+  f2 ();
+  if (n)
+    f1 ();
+  n = 1;
+ lab:
+  n++;
+}
index b69ec0cd2112f29cc3fa8855917cfb5e39ee09b9..4df58550c051f0f8e075b5c13cc83fdc9784a106 100644 (file)
@@ -114,6 +114,7 @@ static void make_goto_expr_edges (basic_block);
 static edge tree_redirect_edge_and_branch (edge, basic_block);
 static edge tree_try_redirect_by_replacing_jump (edge, basic_block);
 static void split_critical_edges (void);
+static bool remove_fallthru_edge (VEC(edge) *);
 
 /* Various helpers.  */
 static inline bool stmt_starts_bb_p (tree, tree);
@@ -2059,7 +2060,7 @@ cleanup_control_flow (void)
   basic_block bb;
   block_stmt_iterator bsi;
   bool retval = false;
-  tree stmt;
+  tree stmt, call;
 
   FOR_EACH_BB (bb)
     {
@@ -2072,6 +2073,17 @@ cleanup_control_flow (void)
       if (TREE_CODE (stmt) == COND_EXPR
          || TREE_CODE (stmt) == SWITCH_EXPR)
        retval |= cleanup_control_expr_graph (bb, bsi);
+
+      /* Check for indirect calls that have been turned into
+        noreturn calls.  */
+      call = get_call_expr_in (stmt);
+      if (call != 0
+         && (call_expr_flags (call) & ECF_NORETURN) != 0
+         && remove_fallthru_edge (bb->succs))
+       {
+         free_dominance_info (CDI_DOMINATORS);
+         retval = true;
+       }
     }
   return retval;
 }
@@ -2140,6 +2152,22 @@ cleanup_control_expr_graph (basic_block bb, block_stmt_iterator bsi)
   return retval;
 }
 
+/* Remove any fallthru edge from EV.  Return true if an edge was removed.  */
+
+static bool
+remove_fallthru_edge (VEC(edge) *ev)
+{
+  edge_iterator ei;
+  edge e;
+
+  FOR_EACH_EDGE (e, ei, ev)
+    if ((e->flags & EDGE_FALLTHRU) != 0)
+      {
+       remove_edge (e);
+       return true;
+      }
+  return false;
+}
 
 /* Given a basic block BB ending with COND_EXPR or SWITCH_EXPR, and a
    predicate VAL, return the edge that will be taken out of the block.