+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
+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.
--- /dev/null
+/* 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++;
+}
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);
basic_block bb;
block_stmt_iterator bsi;
bool retval = false;
- tree stmt;
+ tree stmt, call;
FOR_EACH_BB (bb)
{
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;
}
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.