/* CFG cleanup for trees.
- Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This file is part of GCC.
#include "hard-reg-set.h"
#include "basic-block.h"
#include "output.h"
-#include "errors.h"
+#include "toplev.h"
#include "flags.h"
#include "function.h"
#include "expr.h"
#include "cfglayout.h"
#include "hashtab.h"
#include "tree-ssa-propagate.h"
+#include "tree-scalar-evolution.h"
/* Remove any fallthru edge from EV. Return true if an edge was removed. */
{
edge e;
edge_iterator ei;
+ bool warned;
+
+ fold_defer_overflow_warnings ();
switch (TREE_CODE (expr))
{
case SWITCH_EXPR:
val = fold (SWITCH_COND (expr));
if (TREE_CODE (val) != INTEGER_CST)
- return false;
+ {
+ fold_undefer_and_ignore_overflow_warnings ();
+ return false;
+ }
break;
default:
taken_edge = find_taken_edge (bb, val);
if (!taken_edge)
- return false;
+ {
+ fold_undefer_and_ignore_overflow_warnings ();
+ return false;
+ }
/* Remove all the edges except the one that is always executed. */
+ warned = false;
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
{
if (e != taken_edge)
{
+ if (!warned)
+ {
+ fold_undefer_overflow_warnings
+ (true, expr, WARN_STRICT_OVERFLOW_CONDITIONAL);
+ warned = true;
+ }
+
taken_edge->probability += e->probability;
taken_edge->count += e->count;
remove_edge (e);
else
ei_next (&ei);
}
+ if (!warned)
+ fold_undefer_and_ignore_overflow_warnings ();
if (taken_edge->probability > REG_BR_PROB_BASE)
taken_edge->probability = REG_BR_PROB_BASE;
}
else
taken_edge = single_succ_edge (bb);
- bsi_remove (&bsi);
+ bsi_remove (&bsi, true);
taken_edge->flags = EDGE_FALLTHRU;
/* We removed some paths from the cfg. */
return retval;
}
-/* A list of all the noreturn calls passed to modify_stmt.
- cleanup_control_flow uses it to detect cases where a mid-block
- indirect call has been turned into a noreturn call. When this
- happens, all the instructions after the call are no longer
- reachable and must be deleted as dead. */
-
-VEC(tree,gc) *modified_noreturn_calls;
-
/* Try to remove superfluous control structures. */
static bool
tree stmt;
/* Detect cases where a mid-block call is now known not to return. */
- while (VEC_length (tree, modified_noreturn_calls))
- {
- stmt = VEC_pop (tree, modified_noreturn_calls);
- bb = bb_for_stmt (stmt);
- if (bb != NULL && last_stmt (bb) != stmt && noreturn_call_p (stmt))
- split_block (bb, stmt);
- }
+ if (cfun->gimple_df)
+ while (VEC_length (tree, MODIFIED_NORETURN_CALLS (cfun)))
+ {
+ stmt = VEC_pop (tree, MODIFIED_NORETURN_CALLS (cfun));
+ bb = bb_for_stmt (stmt);
+ if (bb != NULL && last_stmt (bb) != stmt && noreturn_call_p (stmt))
+ split_block (bb, stmt);
+ }
FOR_EACH_BB (bb)
{
bsi = bsi_last (bb);
+ /* If the last statement of the block could throw and now cannot,
+ we need to prune cfg. */
+ retval |= tree_purge_dead_eh_edges (bb);
+
if (bsi_end_p (bsi))
continue;
stmt = bsi_stmt (bsi);
+
if (TREE_CODE (stmt) == COND_EXPR
|| TREE_CODE (stmt) == SWITCH_EXPR)
retval |= cleanup_control_expr_graph (bb, bsi);
-
/* If we had a computed goto which has a compile-time determinable
destination, then we can eliminate the goto. */
- if (TREE_CODE (stmt) == GOTO_EXPR
- && TREE_CODE (GOTO_DESTINATION (stmt)) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (GOTO_DESTINATION (stmt), 0)) == LABEL_DECL)
+ else if (TREE_CODE (stmt) == GOTO_EXPR
+ && TREE_CODE (GOTO_DESTINATION (stmt)) == ADDR_EXPR
+ && (TREE_CODE (TREE_OPERAND (GOTO_DESTINATION (stmt), 0))
+ == LABEL_DECL))
{
edge e;
tree label;
/* Remove the GOTO_EXPR as it is not needed. The CFG has all the
relevant information we need. */
- bsi_remove (&bsi);
+ bsi_remove (&bsi, true);
retval = true;
}
/* Check for indirect calls that have been turned into
noreturn calls. */
- if (noreturn_call_p (stmt) && remove_fallthru_edge (bb->succs))
+ else if (noreturn_call_p (stmt) && remove_fallthru_edge (bb->succs))
{
free_dominance_info (CDI_DOMINATORS);
retval = true;
tree_forwarder_block_p (basic_block bb, bool phi_wanted)
{
block_stmt_iterator bsi;
+ edge_iterator ei;
+ edge e, succ;
+ basic_block dest;
/* BB must have a single outgoing edge. */
if (single_succ_p (bb) != 1
return false;
}
+ /* If we have an EH edge leaving this block, make sure that the
+ destination of this block has only one predecessor. This ensures
+ that we don't get into the situation where we try to remove two
+ forwarders that go to the same basic block but are handlers for
+ different EH regions. */
+ succ = single_succ_edge (bb);
+ dest = succ->dest;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ {
+ if (e->flags & EDGE_EH)
+ {
+ if (!single_pred_p (dest))
+ return false;
+ }
+ }
+
return true;
}
{
label = bsi_stmt (bsi);
gcc_assert (TREE_CODE (label) == LABEL_EXPR);
- bsi_remove (&bsi);
+ bsi_remove (&bsi, false);
bsi_insert_before (&bsi_to, label, BSI_CONTINUE_LINKING);
}
}
{
basic_block bb;
bool changed = false;
- basic_block *worklist = xmalloc (sizeof (basic_block) * n_basic_blocks);
+ basic_block *worklist = XNEWVEC (basic_block, n_basic_blocks);
basic_block *current = worklist;
FOR_EACH_BB (bb)
/* Cleanup cfg and repair loop structures. */
-void
+bool
cleanup_tree_cfg_loop (void)
{
- bitmap changed_bbs = BITMAP_ALLOC (NULL);
+ bool changed = cleanup_tree_cfg ();
- cleanup_tree_cfg ();
-
- fix_loop_structure (current_loops, changed_bbs);
- calculate_dominance_info (CDI_DOMINATORS);
+ if (changed)
+ {
+ bitmap changed_bbs = BITMAP_ALLOC (NULL);
+ calculate_dominance_info (CDI_DOMINATORS);
+ fix_loop_structure (changed_bbs);
- /* This usually does nothing. But sometimes parts of cfg that originally
- were inside a loop get out of it due to edge removal (since they
- become unreachable by back edges from latch). */
- rewrite_into_loop_closed_ssa (changed_bbs, TODO_update_ssa);
+ /* This usually does nothing. But sometimes parts of cfg that originally
+ were inside a loop get out of it due to edge removal (since they
+ become unreachable by back edges from latch). */
+ rewrite_into_loop_closed_ssa (changed_bbs, TODO_update_ssa);
- BITMAP_FREE (changed_bbs);
+ BITMAP_FREE (changed_bbs);
#ifdef ENABLE_CHECKING
- verify_loop_structure (current_loops);
+ verify_loop_structure ();
#endif
+ scev_reset ();
+ }
+ return changed;
}
/* Merge the PHI nodes at BB into those at BB's sole successor. */
<L10>:;
*/
-static void
+static unsigned int
merge_phi_nodes (void)
{
- basic_block *worklist = xmalloc (sizeof (basic_block) * n_basic_blocks);
+ basic_block *worklist = XNEWVEC (basic_block, n_basic_blocks);
basic_block *current = worklist;
basic_block bb;
else
{
tree phi;
+ unsigned int dest_idx = single_succ_edge (bb)->dest_idx;
/* BB dominates DEST. There may be many users of the PHI
nodes in BB. However, there is still a trivial case we
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
tree result = PHI_RESULT (phi);
- int num_uses = num_imm_uses (result);
use_operand_p imm_use;
tree use_stmt;
/* If the PHI's result is never used, then we can just
ignore it. */
- if (num_uses == 0)
+ if (has_zero_uses (result))
continue;
/* Get the single use of the result of this PHI node. */
if (!single_imm_use (result, &imm_use, &use_stmt)
|| TREE_CODE (use_stmt) != PHI_NODE
- || bb_for_stmt (use_stmt) != dest)
+ || bb_for_stmt (use_stmt) != dest
+ || PHI_ARG_DEF (use_stmt, dest_idx) != result)
break;
}
- /* If the loop above iterated thorugh all the PHI nodes
+ /* If the loop above iterated through all the PHI nodes
in BB, then we can merge the PHIs from BB into DEST. */
if (!phi)
*current++ = bb;
}
free (worklist);
+ return 0;
}
static bool