int old_size = gimple_switch_num_labels (stmt);
int i, next_index, new_size;
basic_block default_bb = NULL;
- hash_set<tree> *removed_labels = NULL;
default_bb = gimple_switch_default_bb (cfun, stmt);
gcc_assert (base_case);
base_bb = label_to_block (cfun, CASE_LABEL (base_case));
- /* Discard cases that have the same destination as the default case or
- whose destination blocks have already been removed as unreachable. */
+ /* Discard cases that have the same destination as the default case. */
if (base_bb == NULL
- || base_bb == default_bb
- || (removed_labels
- && removed_labels->contains (CASE_LABEL (base_case))))
+ || base_bb == default_bb)
{
i++;
continue;
/* Merge the cases if they jump to the same place,
and their ranges are consecutive. */
if (merge_bb == base_bb
- && (removed_labels == NULL
- || !removed_labels->contains (CASE_LABEL (merge_case)))
&& wi::to_wide (CASE_LOW (merge_case)) == bhp1)
{
base_high
break;
}
- /* Discard cases that have an unreachable destination block. */
- if (EDGE_COUNT (base_bb->succs) == 0
- && gimple_seq_unreachable_p (bb_seq (base_bb))
- /* Don't optimize this if __builtin_unreachable () is the
- implicitly added one by the C++ FE too early, before
- -Wreturn-type can be diagnosed. We'll optimize it later
- during switchconv pass or any other cfg cleanup. */
- && (gimple_in_ssa_p (cfun)
- || (LOCATION_LOCUS (gimple_location (last_nondebug_stmt (base_bb)))
- != BUILTINS_LOCATION)))
- {
- edge base_edge = find_edge (gimple_bb (stmt), base_bb);
- if (base_edge != NULL)
- {
- for (gimple_stmt_iterator gsi = gsi_start_bb (base_bb);
- !gsi_end_p (gsi); gsi_next (&gsi))
- if (glabel *stmt = dyn_cast <glabel *> (gsi_stmt (gsi)))
- {
- if (FORCED_LABEL (gimple_label_label (stmt))
- || DECL_NONLOCAL (gimple_label_label (stmt)))
- {
- /* Forced/non-local labels aren't going to be removed,
- but they will be moved to some neighbouring basic
- block. If some later case label refers to one of
- those labels, we should throw that case away rather
- than keeping it around and referring to some random
- other basic block without an edge to it. */
- if (removed_labels == NULL)
- removed_labels = new hash_set<tree>;
- removed_labels->add (gimple_label_label (stmt));
- }
- }
- else
- break;
- remove_edge_and_dominated_blocks (base_edge);
- }
- i = next_index;
- continue;
- }
-
if (new_size < i)
gimple_switch_set_label (stmt, new_size,
gimple_switch_label (stmt, i));
if (new_size < old_size)
gimple_switch_set_num_labels (stmt, new_size);
- delete removed_labels;
return new_size < old_size;
}