https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77445
James Greenhalgh <jgreenhalgh at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Last reconfirmed|2016-09-03 00:00:00 |2016-11-30 CC| |law at gcc dot gnu.org --- Comment #5 from James Greenhalgh <jgreenhalgh at gcc dot gnu.org> --- I posted this on list a few weeks back: https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01454.html The early threader is running with speed_p set to false (second parameter to find_jump_threads_backwards) unsigned int pass_early_thread_jumps::execute (function *fun) { /* Try to thread each block with more than one successor. */ basic_block bb; FOR_EACH_BB_FN (bb, fun) { if (EDGE_COUNT (bb->succs) > 1) find_jump_threads_backwards (bb, false); } thread_through_all_blocks (true); return 0; } So even though profile information is ignored, we think we are compiling for size and won't thread. The relevant check in profitable_jump_thread_path is: if (speed_p && optimize_edge_for_speed_p (taken_edge)) { <snip> } else if (n_insns > 1) { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "FSM jump-thread path not considered: " "duplication of %i insns is needed and optimizing for size.\n", n_insns); path->pop (); return NULL; } Changing false to true (or even to optimize_bb_for_size_p ) in the above hunk looks like it would enable some of the threading we're relying on here.