This simplifies (and for me robustifies) finding of the final_bb. The current code is somewhat odd in that it requires at least one non-forwarder successor of a switch to transform. The following patch makes us simply pick the candidate from a random edge (I chose the default edge) using either the successor or its successor if the successor is a forwarder.
That fixes fallout of gcc.dg/tree-ssa/pr36881.c when removing the early copyprop pass which happened to unconditionally run a cfgcleanup. Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Richard. 2014-06-17 Richard Biener <rguent...@suse.de> * tree-switch-conversion.c (collect_switch_conv_info): Simplify and allow all blocks to be forwarders. Index: gcc/tree-switch-conversion.c =================================================================== *** gcc/tree-switch-conversion.c (revision 211727) --- gcc/tree-switch-conversion.c (working copy) *************** collect_switch_conv_info (gimple swtch, *** 640,654 **** info->other_count += e->count; /* See if there is one common successor block for all branch ! targets. If it exists, record it in FINAL_BB. */ ! FOR_EACH_EDGE (e, ei, info->switch_bb->succs) ! { ! if (! single_pred_p (e->dest)) ! { ! info->final_bb = e->dest; ! break; ! } ! } if (info->final_bb) FOR_EACH_EDGE (e, ei, info->switch_bb->succs) { --- 640,655 ---- info->other_count += e->count; /* See if there is one common successor block for all branch ! targets. If it exists, record it in FINAL_BB. ! Start with the destination of the default case as guess ! or its destination in case it is a forwarder block. */ ! if (! single_pred_p (e_default->dest)) ! info->final_bb = e_default->dest; ! else if (single_succ_p (e_default->dest) ! && ! single_pred_p (single_succ (e_default->dest))) ! info->final_bb = single_succ (e_default->dest); ! /* Require that all switch destinations are either that common ! FINAL_BB or a forwarder to it. */ if (info->final_bb) FOR_EACH_EDGE (e, ei, info->switch_bb->succs) {