On Wed, 11 Feb 2026, Jakub Jelinek wrote:

> Hi!
> 
> The following testcase is miscompiled, because after_md_seq which is
> what is emitted for "=@cc?" outputs to initialize a pseudo with
> the result is emitted just once, on the asm goto fallthru edge, before
> after_rtl_seq (on that edge that is the correct ordering), but a copy
> of after_rtl_seq is also emitted on the other edges from asm goto, but
> after_md_seq is not.
> So, the pseudo with the flags checking is initialized only in the
> fallthru case and not when asm goto is left through one of the other
> labels (unless those are degenerate).
> 
> The following patch arranges to emit that sequence duplicated on all the
> edges before after_rtl_seq sequence, by modifying after_rtl_seq so that
> it includes after_md_seq followed by the old after_rtl_seq.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Richard.

> 2026-02-11  Jakub Jelinek  <[email protected]>
> 
>       PR middle-end/124056
>       * cfgexpand.cc (expand_asm_stmt): If after_md_seq is non-NULL, emit
>       it at the start of after_rtl_seq instead of after fallthru_label.
> 
>       * gcc.target/i386/pr124056.c: New test.
> 
> --- gcc/cfgexpand.cc.jj       2026-01-14 17:08:42.000000000 +0100
> +++ gcc/cfgexpand.cc  2026-02-10 17:22:00.117976515 +0100
> @@ -3786,13 +3786,22 @@ expand_asm_stmt (gasm *stmt)
>       Case in point is when the i386 backend moved from cc0 to a hard reg --
>       maintaining source-level compatibility means automatically clobbering
>       the flags register.  */
> -  rtx_insn *after_md_seq = NULL;
>    auto_vec<rtx> use_rvec;
>    if (targetm.md_asm_adjust)
> -    after_md_seq
> +    {
> +      rtx_insn *after_md_seq
>       = targetm.md_asm_adjust (output_rvec, input_rvec, input_mode,
>                                constraints, use_rvec, clobber_rvec,
>                                clobbered_regs, locus);
> +      if (after_md_seq)
> +     {
> +       push_to_sequence (after_md_seq);
> +       emit_insn (after_rtl_seq);
> +       after_rtl_seq = get_insns ();
> +       after_rtl_end = get_last_insn ();
> +       end_sequence ();
> +     }
> +    }
>  
>    /* Do not allow the hook to change the output and input count,
>       lest it mess up the operand numbering.  */
> @@ -3967,8 +3976,6 @@ expand_asm_stmt (gasm *stmt)
>    if (fallthru_label)
>      emit_label (fallthru_label);
>  
> -  if (after_md_seq)
> -    emit_insn (after_md_seq);
>    if (after_rtl_seq)
>      {
>        if (nlabels == 0)
> --- gcc/testsuite/gcc.target/i386/pr124056.c.jj       2026-02-10 
> 17:51:25.191164967 +0100
> +++ gcc/testsuite/gcc.target/i386/pr124056.c  2026-02-10 17:50:58.833610141 
> +0100
> @@ -0,0 +1,61 @@
> +/* PR middle-end/124056 */
> +/* { dg-do run } */
> +/* { dg-options "-O2 -masm=att" } */
> +
> +int v;
> +
> +[[gnu::noipa]] void
> +foo (void)
> +{
> +  v = 42;
> +}
> +
> +[[gnu::noipa]] void
> +bar (void)
> +{
> +  v = 43;
> +}
> +
> +[[gnu::noipa]] int
> +baz (void)
> +{
> +  bool err;
> +  __asm goto ("movl %1, %%ecx\n\t"
> +            "test %%ecx, %%ecx\n\t"
> +            "js 1f\n\t"
> +            "jmp %l[lab]\n\t"
> +         "1: cmpl $-1, %%ecx"
> +            : "=@ccz" (err) : "m" (v) : "ecx" : lab);
> +  if (err)
> +    {
> +      bar ();
> +      return -1;
> +    }
> +  return 0;
> +
> + lab:
> +  if (err)
> +    {
> +      foo ();
> +      return -2;
> +    }
> +
> +  return 1;
> +}
> +
> +int
> +main ()
> +{
> +  v = 0;
> +  if (baz () != -2 || v != 42)
> +    __builtin_abort ();
> +  v = 1;
> +  if (baz () != 1 || v != 1)
> +    __builtin_abort ();
> +  v = -1;
> +  if (baz () != -1 || v != 43)
> +    __builtin_abort ();
> +  v = -2;
> +  if (baz () != 0 || v != -2)
> +    __builtin_abort ();
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to