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)
