https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96632
Bug ID: 96632
Summary: missed-optimization with conditionally unsetting bits
in memory.
Product: gcc
Version: 10.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: goldstein.w.n at gmail dot com
Target Milestone: ---
https://stackoverflow.com/questions/63432157/why-does-gcc-use-btq-in-conjunction-with-btcq-when-conditionally-set-a-bit-in-a
Basically:
void __attribute__((noinline))
cond_unset_bit(uint64_t * v, uint32_t b) {
if(__builtin_expect(!!(*v & ((1UL) << b)), 1)) {
*v ^= ((1UL) << b);
}
}
Compiles to:
cond_unset_bit(unsigned long*, unsigned int):
movq (%rdi), %rax
btq %rsi, %rax
jnc .L6
btcq %rsi, %rax
movq %rax, (%rdi)
.L6:
ret
The btq instruction is unnecessary.
cond_unset_bit(unsigned long*, unsigned int):
movq (%rdi), %rax
btcq %rsi, %rax
jnc .L6
movq %rax, (%rdi)
.L6:
ret
Accomplishes the same thing without the btq instruction.