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?