这个不包含任何循环的简单代码是否会在汇编中生成循环?

问题描述 投票:0回答:1

我正在使用这段代码来检查一个整数是否是 4 的幂:

// C++ version

bool is_pow_4(unsigned a) {
    return (std::popcount(a) == 1) && (std::countr_zero(a) % 2 == 0);
}
// C version

int is_pow_4(unsigned a) {
   return (__builtin_popcount(a) == 1) && (__builtin_ctz(a) % 2 == 0);
}

基本上,我检查是否只有一位被设置,并且它位于一个奇怪的位置。

我期待一个无分支代码,但是我看到两个跳转和一个

rep
指令。据我所知,
rep
基本上是一个循环,但在汇编级别。看起来
std::countr_zero
/
__builtin_ctz
生成了
rep
指令。

C++ 输出:

is_pow_4(unsigned int):
        lea     edx, [rdi-1]
        mov     ecx, edi
        xor     eax, eax
        xor     ecx, edx
        cmp     edx, ecx
        jb      .L7
.L1:
        ret
.L7:
        mov     eax, 1
        test    edi, edi
        je      .L1
        xor     eax, eax
        rep bsf eax, edi
        not     eax
        and     eax, 1
        ret

C 输出 类似。

我知道循环是受整数(32)的宽度限制的,所以我认为代码的复杂度是

O(1)
,但我仍然很惊讶地发现了一个循环。

我的理解正确吗?这段代码是 x86 上的循环吗?这是因为虽然有 x86 popcount 指令,但没有计数前导/尾随零 x86 指令?

c++ c gcc x86 bit-manipulation
1个回答
0
投票

强制编译器无条件执行这两个评估,然后将它们组合起来。所有计算机上的错误都是零。 True 并不总是等于 1。如果将 false 乘以任何数字,您将得到零(再次为 false)。

bool is_pow_4(unsigned a) {
    return (std::popcount(a) == 1) * (std::countr_zero(a) % 2 == 0);
}
© www.soinside.com 2019 - 2024. All rights reserved.