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.

Reply via email to