https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108199
Andreas Krebbel <krebbel at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Target| |x86_64 Build| |x86_64 Keywords| |wrong-code Host| |x86_64 --- Comment #2 from Andreas Krebbel <krebbel at gcc dot gnu.org> --- The testcase does an assigned between two struct with endianess differing from host endianess (assumed to be little). Here the required byteswaps are supposed to cancel each other out. After that a bitfield comparison on the target struct is done. This comparison uses the wrong byte offset into the bitfield: testb $64, 7(%rdi) jne .L11 On a big endian target the first bits in the bitfield are supposed to reside in the first bytes in memory. The problem appears to get introduced when dead store elimination removes the assignment to the target struct in FRE. Before FRE we have the following: _1 = src_6(D)->a; bswap dst$val_9 = _1; bswap _2 = BIT_FIELD_REF <dst$val_9, 8, 0>; bswap _3 = _2 & 64; if (_3 != 0) ... This would result in 3 bswaps chained to each other. However, after FRE we have only two because the dead store to dst$val is removed. _1 = src_6(D)->a; _2 = BIT_FIELD_REF <_1, 8, 0>; _3 = _2 & 64; if (_3 != 0) Now we have only which cancel each other out. Looks like we have to prevent depending stores/loads with different endianess from getting removed - perhaps by making them also volatile? I think we have to keep the number of memory accesses with foreign endianess constant over the optimizations.