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

liu zhenyu <lzy20000419 at outlook dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |lzy20000419 at outlook dot com

--- Comment #3 from liu zhenyu <lzy20000419 at outlook dot com> ---
PR127926 covers the memcpy case of `vn_reference_lookup_3`. The memset case in
the same function has the same
missing `reverse_storage_order_for_component_p` guard (tree-ssa-sccvn.cc,
gcc-14 ~2924-3066). Constant / SSA /
vectorizer-internal store cases already check it; memset does not.

```c
struct __attribute__((scalar_storage_order ("big-endian"))) S { unsigned a : 5;
};

__attribute__((noipa)) unsigned
f (void)
{
  struct S s;
  __builtin_memset (&s, 0x5a, sizeof s);
  return s.a;   /* top 5 bits of 0x5a = 11 */
}

int main (void)
{
  if (f () != 11)
    __builtin_abort ();
  return 0;
}
```

```
$ gcc -O0 t.c && ./a.out   # ok
$ gcc -O1 t.c && ./a.out   # Aborted (f returns 26 = low 5 bits / LE order)
```

Fails at -O1/-O2/-O3/-Os/-Og from GCC 10.1 through trunk (9.4 and older OK).
FRE replaces `s.a` with 26.
`-fno-tree-fre -fno-tree-pre` alone is not enough at -O2 (`-fcode-hoisting`
still folds it). No UB; the only
scalar access is through the big-endian struct itself (same pattern as
gcc.dg/sso and this PR's memcpy tests).

A whole-word masked form also fails (partial memset + `s.w & 1` prints 0
instead of 1), so a fix should not
punt only for non-byte-sized reads.

If the fix for this PR is only in the memcpy case, the memset path would still
need the same guard.

Disclaimer: This test case was generated by a fuzzer, and the report was
written with LLM assistance.

Reply via email to