https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125932
liu zhenyu <lzy20000419 at outlook dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |lzy20000419 at outlook dot com
--- Comment #4 from liu zhenyu <lzy20000419 at outlook dot com> ---
Here is a wrong-code testcase with the same root cause as this ICE (STV
conversion copies placed only on the fallthrough edge of an asm goto with
outputs):
```c
typedef int v4si __attribute__ ((vector_size (16)));
int a;
__attribute__((noipa)) void
f (v4si c, int v, int t)
{
int x;
asm goto ("movl %1, %0\n\ttestl %2, %2\n\tjnz %l[l1]"
: "=&r" (x) : "r" (v), "r" (t) : : l1);
a = x & c[1] & c[2] & c[3];
return;
l1:
a = x & c[0] & c[2] & c[3];
}
int
main (void)
{
v4si m = { -1, -1, -1, -1 };
f (m, 0x1234, 1);
if (a != 0x1234) __builtin_abort ();
f (m, 0x5678, 0);
if (a != 0x5678) __builtin_abort ();
return 0;
}
```
```
$ gcc -O2 t.c && ./a.out
Aborted
$ gcc -O2 -mno-stv t.c && ./a.out
$ gcc -O2 -S -o - t.c
f:
movl %edi, %eax
testl %esi, %esi
jnz .L2
movd %eax, %xmm2 <- x copied into the chain register on the
fallthrough path only
pshufd $85, %xmm0, %xmm1
pand %xmm2, %xmm1
...
ret
.L2:
movdqa %xmm0, %xmm1
pand %xmm2, %xmm1 <- %xmm2 is never set on this path
...
```
Outputs of asm goto are valid on all paths, so a must be 0x1234 after the first
call. Fails at -O2 and -O3 with 14.2.0 and 17.0.0 (20261105); -O1, -Os and
-mno-stv are fine.
Cause: scalar_chain::emit_conversion_insns
(config/i386/i386-features.cc:917-931 on trunk). When the def insn is a
control-flow insn, the copy into the chain register is emitted only after
split_edge of the fallthrough edge. That is enough for a def that can throw,
but an asm goto with outputs is a JUMP_INSN whose outputs are live on every
outgoing edge, so the goto edges get no copy (this testcase). When the asm goto
label is the fallthrough block itself, split_edge on that edge produces the
broken CFG of comment 0.
A fix along these lines (copy the conversion sequence onto every outgoing edge
of a JUMP_P def) fixes this testcase and the comment 0 testcase (no ICE with
checking) on a local 14.2 build; I have not run the testsuite, but -O2 asm for
about 400 gcc.target/i386 stv*/pr* tests (-m64 and -m32 -msse2) is unchanged:
```diff
--- a/gcc/config/i386/i386-features.cc
+++ b/gcc/config/i386/i386-features.cc
@@ scalar_chain::emit_conversion_insns
basic_block bb = BLOCK_FOR_INSN (after);
+
+ /* An asm goto with outputs defines its outputs on every outgoing
+ edge, so the conversion has to be done on all of them. */
+ if (JUMP_P (after))
+ {
+ edge e;
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ {
+ start_sequence ();
+ for (rtx_insn *i = insns; i; i = NEXT_INSN (i))
+ emit_insn (copy_insn (PATTERN (i)));
+ rtx_insn *copy = get_insns ();
+ end_sequence ();
+ insert_insn_on_edge (copy, e);
+ }
+ commit_edge_insertions ();
+ return;
+ }
+
edge e = find_fallthru_edge (bb->succs);
gcc_assert (e);
```
Disclaimer: This test case was found with LLM-assisted targeted testing, and
the report was written with LLM assistance.