https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123386

--- Comment #6 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jakub Jelinek <[email protected]>:

https://gcc.gnu.org/g:c158d510ee96158a4f90255148222fb1ce356832

commit r16-7447-gc158d510ee96158a4f90255148222fb1ce356832
Author: Jakub Jelinek <[email protected]>
Date:   Wed Feb 11 11:31:26 2026 +0100

    cfgrtl: Fix up force_nonfallthru_and_redirect asm goto handling [PR123386]

    force_nonfallthru_and_redirect has some extra code to handle asm gotos
    if we are forcing or redirecting the EDGE_FALLTHRU in case.  This was
    done for PR51767, PR53589, PR54127.
    It is done for the cases where some asm goto label points to the bb
    after the fallthru edge (i.e. there is edge sharing between the fallthru
    and the label, partly or fully degenerate asm goto) and/or if the label
    points to the TARGET bb (before/after).
    In such case it changes the label from e->dest's label to target's label
    and similarly to the case of 2+ successor e->src a new bb is created
    as new fallthru from e->src and in the asm goto case an additional edge
    is added, so there is
     |
    asm goto -----+    maybe other edges
     | fallthru    \
     v              v
     jumpblock -> target
    and the jumpblock -> target edge isn't EDGE_FALLTHRU.
    This was done that way to fix various ICEs with the degenerate asm gotos,
    see above for list.
    I believe it will still ICE if we decide to force_nonfallthru_and_redirect
    E bb5->bb6 to l2, because in that case there are already two+ edges, one
    pointing from bb5->l2 and we create another edge bb5->l2:
    bb5:
    asm goto ("" : : : : (l2));
    bb6:
    ...
    l2:
    but maybe nothing tries that in that case.  Anyway, the reason why
    the following two (PR116600 and PR123386) testcases are miscompiled is
    that we try to (during shrink-wrapping) emit some insns on the bb3->bb7
    edge, and see bb7 predecessor edge is EDGE_FALLTHRU in:
    bb3:
      __asm__ goto ("" : : : : d);
      if (c)
        bar (a);
    bb6:
      __asm__ goto ("" : : : : d);
    d: // == bb7
    in rtl_split_edge:
      /* We are going to place the new block in front of edge destination.
         Avoid existence of fallthru predecessors.  */
      if ((edge_in->flags & EDGE_FALLTHRU) == 0)
        {
          edge e = find_fallthru_edge (edge_in->dest->preds);

          if (e)
            force_nonfallthru (e);
        }
    Now, the asm goto in bb6 is degenerate, so shrink-wrapping isn't aware
    that there would be multiple edges from it, there is just single one.
    But we still while splitting the bb3->bb7 edge in order to emit there
    pending insns on that edge turn the single successor asm goto bb into
    one with two successors (initially with two different ways to reach
    the same destination).  But unfortunately such change confuses the
    shrink-wrapping logic which isn't aware of such a change and so the
    separate shrink wrapping insns end up just on one of the paths instead
    of being on both, and we then ICE in dwarf2 pass because there is an
    disagreement on the CFI state (of course it is a wrong-code too).

    Note, force_nonfallthru calls force_nonfallthru_and_redirect with
    target set to e->dest.

    The following patch reworks this.
    Instead of creating that
     |
    asm goto -----+    maybe other edges
     | fallthru    \
     v              v
     jumpblock -> target
    for initially degenerate asm goto we now create
     |
    asm goto    maybe other edges
     | fallthru
     v
     jumpblock -> target
    i.e. the asm goto keeps being degenerate, all we've changed is adding
    a new bb on the fallthru edge and making the edge from that new bb
    non-fallthru.  Furthermore, for the case where there would be before
    an asm goto -> target edge before for the e->dest != target case,
    those edges are untouched.
    For the immediate effect after the operation, the asm goto keeps
    the existing behavior, if it falls through, it will reach target
    by hopping through jumpblock, if it jumps to that label, previously
    it jumped directly to target, now it jumps to jumpblock and from there
    to target.  But shrink-wrapping etc. then put the right fixups everywhere
    where it belongs.

    2026-02-11  Jakub Jelinek  <[email protected]>

            PR rtl-optimization/116600
            PR middle-end/123386
            * cfgrtl.cc (force_nonfallthru_and_redirect): Don't do any
            asm goto adjustments early, only note in asm_goto_edge if
            any labels point originally to e->dest head.  After jumpblock
            creation don't add an extra edge for asm_goto_edge, instead
            adjust those labels pointing to former e->dest head to point
            to jumpblock instead.

            * gcc.c-torture/compile/pr116600.c: New test.
            * gcc.c-torture/compile/pr123386.c: New test.

Reply via email to