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?

Reply via email to