On 7/27/17 12:21 PM, Steven Bosscher wrote: > On Wed, Jul 26, 2017 at 9:35 PM, Peter Bergner wrote: >> The test case for PR81564 exposes an issue where the case labels for a >> switch statement point to blocks that have already been removed by an >> earlier call to cleanup_tree_cfg(). In that case, the code in >> group_case_labels_stmt() that does: > > How can a basic block be removed (apparently as unreachable) if there > are still case labels leading to it? > > Apparently there is enough information to make CASE_LABEL be set to > NULL. Why is the case label not just removed (or redirected to the > default, or ...)?
My bad above. The block is actually deleted during the process of grouping the labels. The switch statement we have entering group_case_labels_stmt() is: switch (...) { case 3: case 7: __builtin_unreachable(); } We first handle case "3" and we notice that it leads to an "unreachable" block, so we delete the edge to that block and then the block itself: /* Discard cases that have an unreachable destination block. */ if (EDGE_COUNT (base_bb->succs) == 0 && gimple_seq_unreachable_p (bb_seq (base_bb))) { edge base_edge = find_edge (gimple_bb (stmt), base_bb); if (base_edge != NULL) remove_edge_and_dominated_blocks (base_edge); i = next_index; continue; } Next time through the loop, we handle case "7" which pointed to the same block as case "3", but since we just deleted the block it points to, that is why 'base_bb = label_to_block (CASE_LABEL (base_case));' now returns a NULL basic block. So the incongruous issue you state is just a temporary artifact of the process of cleaning up the unreachable blocks. The NULL basic block is just a sign that we deleted that case's block in an earlier loop iteration, so we're correct in just removing it like the patch does. Sorry for the poor initial description! Peter