https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111743
Bug ID: 111743 Summary: shifts in bit field accesses don't combine with other shifts Product: gcc Version: 13.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: andi-gcc at firstfloor dot org Target Milestone: --- (not sure it's the middle-end, picked arbitrarily) The following code struct bf { unsigned a : 10, b : 20, c : 10; }; unsigned fbc(struct bf bf) { return bf.b | (bf.c << 20); } generates: movq %rdi, %rax shrq $10, %rdi shrq $32, %rax andl $1048575, %edi andl $1023, %eax sall $20, %eax orl %edi, %eax ret It doesn't understand that the shift right can be combined with the shift left. Also not sure why the shift left is arithmetic (this should be all unsigned) clang does the simplification which ends up one instruction shorter: movl %edi, %eax shrl $10, %eax andl $1048575, %eax # imm = 0xFFFFF shrq $12, %rdi andl $1072693248, %edi # imm = 0x3FF00000 orl %edi, %eax retq