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. */
/* 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;
}
{
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)
}
-/* Remove unreachable blocks and other miscellaneous clean up work. */
+/* Remove unreachable blocks and other miscellaneous clean up work.
+ Return true if the flowgraph was modified, false otherwise. */
bool
cleanup_tree_cfg (void)
{
- bool retval;
+ bool retval, changed;
timevar_push (TV_TREE_CLEANUP_CFG);
+ /* Iterate until there are no more cleanups left to do. If any
+ iteration changed the flowgraph, set CHANGED to true. */
+ changed = false;
do
- retval = cleanup_tree_cfg_1 ();
+ {
+ retval = cleanup_tree_cfg_1 ();
+ changed |= retval;
+ }
while (retval);
compact_blocks ();
timevar_pop (TV_TREE_CLEANUP_CFG);
- return retval;
+ return changed;
}
/* Cleanup cfg and repair loop structures. */
static void
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;
nodes at BB. */
*current++ = 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
+ can handle. If the result of every PHI in BB is used
+ only by a PHI in DEST, then we can trivially merge the
+ PHI nodes from BB into DEST. */
+ 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)
+ 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
+ || PHI_ARG_DEF (use_stmt, dest_idx) != result)
+ break;
+ }
+
+ /* If the loop above iterated thorugh all the PHI nodes
+ in BB, then we can merge the PHIs from BB into DEST. */
+ if (!phi)
+ *current++ = bb;
+ }
}
/* Now let's drain WORKLIST. */