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.

Reply via email to