如何解决当在uint64_t *内存区域中有条件地设置位时,为什么gcc与btcq一起使用btq
基本上,我正在尝试了解以下位置的代码:https://gcc.godbolt.org/z/7xxb3G
{3}
编译为:
void __attribute__((noinline))
cond_unset_bit(uint64_t * v,uint32_t b) {
if(__builtin_expect(!!(*v & ((1UL) << b)),1)) {
*v ^= ((1UL) << b);
}
}
基于Agner Fog's Instruction Table(skylake是第238页),cond_unset_bit(unsigned long*,unsigned int):
movq (%rdi),%rax
btq %rsi,%rax
jnc .L6
btcq %rsi,%rax
movq %rax,(%rdi)
.L6:
ret
和btq
在寄存器上进行操作的成本完全相同。 btcq
也会set the carry flag to the previous bit,因此似乎不需要使用btcq
指令即可实现完全相同的逻辑(具有更好的性能),即:
btq
包括cond_unset_bit(unsigned long*,%rax
btcq %rsi,%rax
jnc .L6
movq %rax,(%rdi)
.L6:
ret
的原因是什么?
我正在调整x86_64 / Intel Skylake芯片
编辑: 感谢@Peter Cordes(以及我其他所有帖子的帮助:)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。