aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r--gcc/tree-cfg.c50
1 files changed, 31 insertions, 19 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index a540416..77cb3d6 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -452,6 +452,31 @@ computed_goto_p (gimple *t)
&& TREE_CODE (gimple_goto_dest (t)) != LABEL_DECL);
}
+/* Returns true if the sequence of statements STMTS only contains
+ a call to __builtin_unreachable (). */
+
+bool
+gimple_seq_unreachable_p (gimple_seq stmts)
+{
+ if (stmts == NULL)
+ return false;
+
+ gimple_stmt_iterator gsi = gsi_last (stmts);
+
+ if (!gimple_call_builtin_p (gsi_stmt (gsi), BUILT_IN_UNREACHABLE))
+ return false;
+
+ for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ if (gimple_code (stmt) != GIMPLE_LABEL
+ && !is_gimple_debug (stmt)
+ && !gimple_clobber_p (stmt))
+ return false;
+ }
+ return true;
+}
+
/* Returns true for edge E where e->src ends with a GIMPLE_COND and
the other edge points to a bb with just __builtin_unreachable ().
I.e. return true for C->M edge in:
@@ -476,22 +501,7 @@ assert_unreachable_fallthru_edge_p (edge e)
if (other_bb == e->dest)
other_bb = EDGE_SUCC (pred_bb, 1)->dest;
if (EDGE_COUNT (other_bb->succs) == 0)
- {
- gimple_stmt_iterator gsi = gsi_after_labels (other_bb);
- gimple *stmt;
-
- if (gsi_end_p (gsi))
- return false;
- stmt = gsi_stmt (gsi);
- while (is_gimple_debug (stmt) || gimple_clobber_p (stmt))
- {
- gsi_next (&gsi);
- if (gsi_end_p (gsi))
- return false;
- stmt = gsi_stmt (gsi);
- }
- return gimple_call_builtin_p (stmt, BUILT_IN_UNREACHABLE);
- }
+ return gimple_seq_unreachable_p (bb_seq (other_bb));
}
return false;
}
@@ -1668,9 +1678,11 @@ group_case_labels_stmt (gswitch *stmt)
gcc_assert (base_case);
base_bb = label_to_block (CASE_LABEL (base_case));
- /* Discard cases that have the same destination as the
- default case. */
- if (base_bb == default_bb)
+ /* Discard cases that have the same destination as the default case
+ or if their destination block is unreachable. */
+ if (base_bb == default_bb
+ || (EDGE_COUNT (base_bb->succs) == 0
+ && gimple_seq_unreachable_p (bb_seq (base_bb))))
{
gimple_switch_set_label (stmt, i, NULL_TREE);
i++;