summaryrefslogtreecommitdiff
path: root/gcc/tree-cfgcleanup.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-cfgcleanup.c')
-rw-r--r--gcc/tree-cfgcleanup.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
index c35001c33e7..bd2523bf7e6 100644
--- a/gcc/tree-cfgcleanup.c
+++ b/gcc/tree-cfgcleanup.c
@@ -507,6 +507,36 @@ split_bbs_on_noreturn_calls (void)
return changed;
}
+/* If OMP_RETURN in basic block BB is unreachable, remove it. */
+
+static bool
+cleanup_omp_return (basic_block bb)
+{
+ tree stmt = last_stmt (bb);
+ basic_block control_bb;
+
+ if (stmt == NULL_TREE
+ || TREE_CODE (stmt) != OMP_RETURN
+ || !single_pred_p (bb))
+ return false;
+
+ control_bb = single_pred (bb);
+ stmt = last_stmt (control_bb);
+
+ if (TREE_CODE (stmt) != OMP_SECTIONS_SWITCH)
+ return false;
+
+ /* The block with the control statement normally has two entry edges -- one
+ from entry, one from continue. If continue is removed, return is
+ unreachable, so we remove it here as well. */
+ if (EDGE_COUNT (control_bb->preds) == 2)
+ return false;
+
+ gcc_assert (EDGE_COUNT (control_bb->preds) == 1);
+ remove_edge_and_dominated_blocks (single_pred_edge (bb));
+ return true;
+}
+
/* Tries to cleanup cfg in basic block BB. Returns true if anything
changes. */
@@ -515,8 +545,11 @@ cleanup_tree_cfg_bb (basic_block bb)
{
bool retval = false;
- retval = cleanup_control_flow_bb (bb);
+ if (cleanup_omp_return (bb))
+ return true;
+ retval = cleanup_control_flow_bb (bb);
+
/* Forwarder blocks can carry line number information which is
useful when debugging, so we only clean them up when
optimizing. */