https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127967
liu zhenyu <lzy20000419 at outlook dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |lzy20000419 at outlook dot com
--- Comment #2 from liu zhenyu <lzy20000419 at outlook dot com> ---
The bug is also reachable through a second code path that doesn't go through
the IPA-CP modification walker. A fix that only touches ipcp_modif_dom_walker
would leave this testcase miscompiled:
struct S { unsigned p : 4, q : 8; };
struct S gs;
__attribute__((noinline)) static int f(struct S s)
{ struct S c; c = s; gs = c; return gs.q; }
int main() {
union { unsigned char b[4]; struct S s; } u = {{16}};
__builtin_printf("%d\n", f(u.s));
return 0;
}
It prints 1 at -O0 but 16 at -O2. I see this on GCC 14.2, 15.2 and trunk; 12.5
is fine. The ipa-cp dump shows no "Modifying stmt" here. Instead, fre3 replaces
gs.q with 16, via ipcp_get_aggregate_const, which is called from
tree-ssa-sccvn.cc (line 2435 in 14.2).
Both sites in ipa-prop.cc compute unit_offset = bit_offset / BITS_PER_UNIT
(lines 5669 and 5744 in 14.2) without checking bit_offset % BITS_PER_UNIT. So
s.q, which starts at bit 4, gets truncated to byte 0 and picks up the aggregate
constant for that byte. The only other guard is the size check, and the sizes
happen to match: q is 8 bits, the same as unsigned char. Bailing out when
bit_offset % BITS_PER_UNIT != 0 at both sites should fix both testcases.