https://gcc.gnu.org/g:f108e23d2bff50d0ee8cf0d25a08be5432b702b6
commit r17-536-gf108e23d2bff50d0ee8cf0d25a08be5432b702b6 Author: Andrew Pinski <[email protected]> Date: Wed May 13 21:24:43 2026 -0700 tree-cfg: Revert part of r8-546 [PR125290] This reverts the group_case_labels_stmt part of r8-546-gca4d2851687875. This is placed in the wrong location to remove the case statements that go directly to __builtin_unreachable. In fact the removal of the case statements make us lose optimizations in some cases (Wuninitialized-pr107919-1.C for one). Also this fixes PR 125290 by no longer leaving around a switch which just has a default case. Bootstrapped and tested on x86_64-linux-gnu. PR tree-optimization/125290 gcc/ChangeLog: * tree-cfg.cc (group_case_labels_stmt): Remove code that was added to remove `cases` that goto blocks of unreachable. * tree-ssa-forwprop.cc (optimize_unreachable): Remove the comment about switch cases being handled. gcc/testsuite/ChangeLog: * g++.dg/warn/Wuninitialized-pr107919-1.C: Remove xfail. * gcc.dg/analyzer/taint-assert.c: Update for the non-removal of block containing unreachable. * gcc.dg/torture/pr125290-1.c: New test. Signed-off-by: Andrew Pinski <[email protected]> Diff: --- .../g++.dg/warn/Wuninitialized-pr107919-1.C | 2 +- gcc/testsuite/gcc.dg/analyzer/taint-assert.c | 4 +- gcc/testsuite/gcc.dg/torture/pr125290-1.c | 40 +++++++++++++++++ gcc/tree-cfg.cc | 51 +--------------------- gcc/tree-ssa-forwprop.cc | 3 +- 5 files changed, 46 insertions(+), 54 deletions(-) diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-pr107919-1.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-pr107919-1.C index 049fa4d307ae..b3ed4628bdda 100644 --- a/gcc/testsuite/g++.dg/warn/Wuninitialized-pr107919-1.C +++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-pr107919-1.C @@ -14,4 +14,4 @@ void do_something(void* storage) std::swap(event, swappedValue); } -// { dg-bogus "may be used uninitialized" "" { xfail *-*-* } 0 } +// { dg-bogus "may be used uninitialized" "" 0 } diff --git a/gcc/testsuite/gcc.dg/analyzer/taint-assert.c b/gcc/testsuite/gcc.dg/analyzer/taint-assert.c index a858e996a801..e46cbe95801d 100644 --- a/gcc/testsuite/gcc.dg/analyzer/taint-assert.c +++ b/gcc/testsuite/gcc.dg/analyzer/taint-assert.c @@ -322,8 +322,8 @@ test_switch_bogus_case_unreachable (int n) case 2: return -1; case 42: - /* This case gets optimized away before we see it. */ - __builtin_unreachable (); + /* The wording is rather inaccurate here. */ + __builtin_unreachable (); /* { dg-warning "use of attacked-controlled value in condition for assertion" } */ } } diff --git a/gcc/testsuite/gcc.dg/torture/pr125290-1.c b/gcc/testsuite/gcc.dg/torture/pr125290-1.c new file mode 100644 index 000000000000..6183cbd26819 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr125290-1.c @@ -0,0 +1,40 @@ +/* PR tree-optimization/125290 */ +/* { dg-do compile } */ + +int g21; +int g31, f14f16_c12; +void f14f16() +{ + short v7; + long v9; + long v13; + if (g31) + { + g21 = 0; + switch (v7) + { + case 4: + case 66: break; + default: __builtin_unreachable(); + } + } + else + { + lbl_bf2: + v9 = g21; + } + v13 = v9; + switch (v13) + { + case 55: + case 2: goto lbl_sw12; + default: + if (f14f16_c12) + goto lbl_bf2; + else + return; + } +lbl_sw12: + __builtin_unreachable(); +} + diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc index b2968c412ed6..5f751e15d9d6 100644 --- a/gcc/tree-cfg.cc +++ b/gcc/tree-cfg.cc @@ -1712,7 +1712,6 @@ group_case_labels_stmt (gswitch *stmt) 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); @@ -1728,12 +1727,9 @@ group_case_labels_stmt (gswitch *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; @@ -1756,8 +1752,6 @@ group_case_labels_stmt (gswitch *stmt) /* 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 @@ -1770,46 +1764,6 @@ group_case_labels_stmt (gswitch *stmt) 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)); @@ -1822,7 +1776,6 @@ group_case_labels_stmt (gswitch *stmt) if (new_size < old_size) gimple_switch_set_num_labels (stmt, new_size); - delete removed_labels; return new_size < old_size; } diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc index 1587fa7bd142..06eb81b9a28d 100644 --- a/gcc/tree-ssa-forwprop.cc +++ b/gcc/tree-ssa-forwprop.cc @@ -5264,8 +5264,7 @@ optimize_unreachable (basic_block bb) } else { - /* Todo: handle other cases. Note that unreachable switch case - statements have already been removed. */ + /* Todo: handle other cases. e.g. switch. */ continue; }
