I've got a case where an unconditional simple jump is being removed, yet it doesn't jump to the next insn. The code in question seems suspect...
Here we force CLEANUP_CFGLAYOUT true: void cfg_layout_initialize (unsigned int flags) { . . . cleanup_cfg (CLEANUP_CFGLAYOUT | flags); } in cleanup_cfg we have this logic: /* If B has a single outgoing edge, but uses a non-trivial jump instruction without side-effects, we can either delete the jump entirely, or replace it with a simple unconditional jump. */ if (single_succ_p (b) && single_succ (b) != EXIT_BLOCK_PTR && onlyjump_p (BB_END (b)) && !find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX) && try_redirect_by_replacing_jump (single_succ_edge (b), single_succ (b), (mode & CLEANUP_CFGLAYOUT) != 0)) It says "non-trivial" but the insn is a simple jump: (jump_insn 45 44 46 5 (set (pc) (label_ref:DI 754))) Note that "mode" of course has CLEANUP_CFGLAYOUT set. Thus, here in try_redirect_by_replacing_jump (note that in_cfglayout is set, from mode above): /* See if we can create the fallthru edge. */ if (in_cfglayout || can_fallthru (src, target)) { if (dump_file) fprintf (dump_file, "Removing jump %i.\n", INSN_UID (insn)); fallthru = 1; /* Selectively unlink whole insn chain. */ if (in_cfglayout) { rtx insn = src->il.rtl->footer; delete_insn_chain (kill_from, BB_END (src)); What seems to happen is, we delete the simple jump even if we can't fallthru, and thus the blocks get rearranged in an incorrect order. Is there a bug here, or am I misunderstanding how this code works?