clang trunk, x86_64, rev321482. > cat f.cpp struct S { short m0; unsigned long long int m2 : 21; short m3 : 16; short m5 : 17; short : 16; }; S z = {-724, 388702ULL, 26720, 2792}; unsigned long long int tf_3_var_136 = 0; void foo() { tf_3_var_136 = ((unsigned short)(z.m0 | z.m2)); z.m5 = 0; } int main() { foo(); __builtin_printf("%llu\n", tf_3_var_136); return 0; } > clang++ -w f.cpp -o outc; g++ -w f.cpp -o outg; ./outc; ./outg 3999203198 65406 Note that clang 5.0 also produces correct result (as gcc in the example above). Slight massaging of the test case make the bug go. You may notice that one of the bit fields is longer than "base" type, i.e. short : 17. But this is a valid C++, according to the standard bits after the "base" type size are just "padding". Anyway, effects triggered by this example are definitely considered as a bug by regular clang users.
This looks related to r320962 [DAGCombine] Move AND nodes to multiple load leaves. Though different than PR35765. Looks like the IR contains an i40 store which triggers a fast-isel abort leading to falling back to SelectionDAG and triggering optimizations. Really strange that -O0 does that when fast-isel aborts.
Patch for review: https://reviews.llvm.org/D41628
Fix committed in https://reviews.llvm.org/rL321862
Keeping this open until merged into 6.00
Merged in r322671.