https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111613
Bug ID: 111613 Summary: Bit field stores can be incorrectly optimized away when -fstore-merging is in effect Product: gcc Version: 12.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: gcc at kempniu dot pl Target Milestone: --- Created attachment 56002 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=56002&action=edit Preprocessed reproducer This is the simplest reproducer I could come up with: $ cat bitfield.c #include <stdio.h> #include <stdlib.h> struct bitfield { unsigned int field1 : 1; unsigned int field2 : 1; unsigned int field3 : 1; }; __attribute__((noinline)) static void set_field1_and_field2(struct bitfield *b) { b->field1 = 1; b->field2 = 1; } __attribute__((noinline)) static struct bitfield * new_bitfield(void) { struct bitfield *b = (struct bitfield *)malloc(sizeof(*b)); b->field3 = 1; set_field1_and_field2(b); return b; } int main(void) { struct bitfield *b = new_bitfield(); printf("%d\n", b->field3); return 0; } $ gcc -O2 -o bitfield bitfield.c $ ./bitfield 0 $ gcc -O2 -fno-store-merging -o bitfield bitfield.c $ ./bitfield 1 Removing one of the stores from set_field1_and_field2() makes the issue go away. Moving "b->field3 = 1;" below the call to set_field1_and_field2() also makes the issue go away. This was originally found for the following GCC version: $ gcc -v Using built-in specs. COLLECT_GCC=/usr/bin/gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/13.2.1/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: /build/gcc/src/gcc/configure --enable-languages=ada,c,c++,d,fortran,go,lto,objc,obj-c++ --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-__cxa_atexit --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 13.2.1 20230801 (GCC) However, I have subsequently confirmed that it also happens on the current master branch. A git bisect points at the following commit as the culprit (first included in GCC 12.1.0): commit 22c242342e38ebffa6bbf7e86e7a1e4abdf0d686 Author: Martin Liska <mli...@suse.cz> Date: Thu Nov 18 17:50:19 2021 +0100 IPA: fix reproducibility in IPA MOD REF gcc/ChangeLog: * ipa-modref.c (analyze_function): Do not execute the code only if dump_file != NULL. Reverting this change on top of current master makes the issue disappear, so it looks legit to me. Disassembly of new_bitfield() for "gcc -O2": 0x0000000000001190 <+0>: sub $0x8,%rsp 0x0000000000001194 <+4>: mov $0x4,%edi 0x0000000000001199 <+9>: call 0x1040 <malloc@plt> 0x000000000000119e <+14>: mov %rax,%rdi 0x00000000000011a1 <+17>: call 0x1180 <set_field1_and_field2> 0x00000000000011a6 <+22>: add $0x8,%rsp 0x00000000000011aa <+26>: ret Disassembly of new_bitfield() for "gcc -O2 -fno-store-merging": 0x0000000000001190 <+0>: sub $0x8,%rsp 0x0000000000001194 <+4>: mov $0x4,%edi 0x0000000000001199 <+9>: call 0x1040 <malloc@plt> 0x000000000000119e <+14>: orb $0x4,(%rax) 0x00000000000011a1 <+17>: mov %rax,%rdi 0x00000000000011a4 <+20>: call 0x1180 <set_field1_and_field2> 0x00000000000011a9 <+25>: add $0x8,%rsp 0x00000000000011ad <+29>: ret