https://gcc.gnu.org/bugzilla/show_bug.cgi?id=18041
--- Comment #7 from Richard Biener <rguenth at gcc dot gnu.org> --- GCC 6 at -O2 on x86_64 produces foo: .LFB0: .cfi_startproc movzbl (%rdi), %eax movl %eax, %edx shrb %dl orl %eax, %edx andl $-2, %eax andl $1, %edx orl %edx, %eax movb %al, (%rdi) ret If we lower bitfield accesses to BIT_FIELD_REF / BIT_INSERT_EXPR we get <bb 2>: _7 = b_5(D)->D.1753; _1 = BIT_FIELD_REF <_7, 1, 0>; _2 = BIT_FIELD_REF <_7, 1, 1>; _3 = _1 | _2; _8 = BIT_INSERT_EXPR <_7, _3, 0 (1 bits)>; b_5(D)->D.1753 = _8; return; if we lower to shifts/masks then <bb 2>: _7 = b_5(D)->D.1753; _11 = _7 >> 1; _1 = _7 | _11; _14 = _7 & 254; _10 = _1 & 1; _16 = _10 | _14; b_5(D)->D.1753 = _16; return; it fails to notice that the & 254 is not necessary. That's easier to grasp from the first lowering.