如何使用MSVC内在函数来获得相当于这个GCC代码?

Dar*_*ari 14 c intrinsics visual-c++

以下代码在GCC中调用clz/ctz的内置函数,在其他系统上调用C版本.显然,如果系统有内置的clz/ctz指令,如x86和ARM,则C版本有点不理想.

#ifdef __GNUC__
#define clz(x) __builtin_clz(x)
#define ctz(x) __builtin_ctz(x)
#else
static uint32_t ALWAYS_INLINE popcnt( uint32_t x )
{
    x -= ((x >> 1) & 0x55555555);
    x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
    x = (((x >> 4) + x) & 0x0f0f0f0f);
    x += (x >> 8);
    x += (x >> 16);
    return x & 0x0000003f;
}
static uint32_t ALWAYS_INLINE clz( uint32_t x )
{
    x |= (x >> 1);
    x |= (x >> 2);
    x |= (x >> 4);
    x |= (x >> 8);
    x |= (x >> 16);
    return 32 - popcnt(x);
}
static uint32_t ALWAYS_INLINE ctz( uint32_t x )
{
    return popcnt((x & -x) - 1);
}

#endif
Run Code Online (Sandbox Code Playgroud)

我需要调用哪些函数,我需要包含哪些标题等,以便在此处为MSVC添加正确的ifdef?我已经查看了这个页面,但是我不完全确定#pragma是什么(它是否需要?)以及它对编译的MSVC版本要求有什么限制.作为一个并不真正使用MSVC的人,我也不知道这些内在函数是否在其他体系结构上具有C等价物,或者在#defining它们时是否还需要#ifdef x86/x86_64.

cra*_*jul 22

从sh0dan代码反弹,实现应该像这样纠正:

#ifdef _MSC_VER
#include <intrin.h>

uint32_t __inline ctz( uint32_t value )
{
    DWORD trailing_zero = 0;

    if ( _BitScanForward( &trailing_zero, value ) )
    {
        return trailing_zero;
    }
    else
    {
        // This is undefined, I better choose 32 than 0
        return 32;
    }
}

uint32_t __inline clz( uint32_t value )
{
    DWORD leading_zero = 0;

    if ( _BitScanReverse( &leading_zero, value ) )
    {
       return 31 - leading_zero;
    }
    else
    {
         // Same remarks as above
         return 32;
    }
}
#endif
Run Code Online (Sandbox Code Playgroud)

正如在代码中所评论的那样,如果值为0,则ctz和clz都是未定义的.在我们的抽象中,我们修复__builtin_clz(value)(value?__builtin_clz(value):32)但它是一个选择

  • MSVC中`__builtin_clz()`的几乎一对一替换是`__lzcnt()`.硬件必须支持SSE4.[更多信息](https://msdn.microsoft.com/en-US/library/bb384809.aspx). (3认同)
  • 我的硬件支持 SSE4,但不支持 BMI1,因此 __lzcnt() 可以编译,但不会执行我期望的操作,而是作为 BSR 工作。 (3认同)
  • `31 ^__builtin_clz` 等于 `_BitScanReverse` (2认同)

Ana*_*tts 0

如果 MSVC 有一个内置的编译器,它会在这里:

MSDN 上的编译器内部函数

否则,你必须使用 __asm 来编写它