aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20050122-1.c12
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20050122-2.c19
-rw-r--r--gcc/tree-cfg.c30
5 files changed, 72 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1a9d9e6..69b5bc1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6b16fc8..c8930cb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..a70907d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20050122-1.c
@@ -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
index 0000000..d73f624
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20050122-2.c
@@ -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++;
+}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index b69ec0c..4df5855 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -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.