内在函数来获得与此

内在函数来获得与此

本文介绍了如何使用 MSVC 内在函数来获得与此 GCC 代码等效的代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The following code calls the builtin functions for clz/ctz in GCC and, on other systems, has C versions. Obviously, the C versions are a bit suboptimal if the system has a builtin clz/ctz instruction, like x86 and ARM.

#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

我需要调用哪些函数,我需要包含哪些标头等,以便在此处为 MSVC 添加适当的 ifdef?我已经看过这个页面,但我并不完全确定#pragma 的用途(是否需要?)以及它对编译的 MSVC 版本要求有何限制.作为一个不真正使用 MSVC 的人,我也不知道这些内在函数是否在其他架构上具有 C 等效项,或者我是否必须在 #defining 它们时 #ifdef x86/x86_64.

What functions do I need to call, which headers do I need to include, etc to add a proper ifdef for MSVC here? I've already looked at this page, but I'm not entirely sure what the #pragma is for (is it required?) and what restrictions it puts on MSVC version requirements for compilation. As someone who doesn't really use MSVC, I also don't know whether these intrinsics have C equivalents on other architectures, or whether I have to #ifdef x86/x86_64 as well when #defining them.

推荐答案

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

Bouncing from sh0dan code, the implementation should be corrected like this :

#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

如代码中所述,如果 value 为 0,则 ctz 和 clz 都未定义.在我们的抽象中,我们将 __builtin_clz(value) 固定为 (value?__builtin_clz(value):32) 但这是一个选择

As commented in the code, both ctz and clz are undefined if value is 0. In our abstraction, we fixed __builtin_clz(value) as (value?__builtin_clz(value):32) but it's a choice

这篇关于如何使用 MSVC 内在函数来获得与此 GCC 代码等效的代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 06:10