XCode 和 _bittest 函数

XCode and _bittest function

我有一个为 Win32 开发的 C++ 小项目,我想将它移植到 OSX。该代码使用 _bittest_bittest64 等函数,但我没有在 XCode 头文件中找到相同的函数。

有什么可以替代这些功能?可能有很好的工作 polyfill。该项目确实是一个遗产,目前不需要额外的性能。

_bittest and _bittest64 symbols are compiler intrinsics, that emit Bit-test instructions, specifically x86 bt,检查从零开始的索引处的位值。

对于内存操作数,bt 具有疯狂的 CISC 位串行为,其中位索引可以超出寻址模式选择的 dword/qword 内存。这很慢,也是编译器首先将操作数加载到寄存器中的原因。但这就是 MSVC 内在函数的用途。否则它不需要是一个内在的。

以下 C++ 匹配 bt 指令的 register-arg 版本的行为,将移位计数包装在寄存器宽度上,即有效地只查看低位。 (如果 b 是 <32 或 <64。,这与 MSVC 内在匹配 。请参阅更新的代码和注释以讨论如何实现 MSVC 语义,使其可以在指向的 longlong long.

之外访问

另请注意,long 在 x64 Windows ABI 中是 32 位类型,但在 x86-64 System V ABI(您在OS X,除非您构建过时的 32 位代码)。您可能希望将代码更改为 int32_tuint32_t,以避免在每个 long 中留下未使用的位,具体取决于您的使用方式。

inline
unsigned char bittest(long const *a, long b)
{
    auto const value{ *a };
    auto const mask{ 1L << (b&31) };
    auto const masked_value{ value & mask };
    return unsigned char{ masked_value != 0 };
}

inline
unsigned char bittest64(long long const *a, long long b)
{
    auto const value{ *a };
    auto const mask{ 1LL << (b&63) };
    auto const masked_value{ value & mask };
    return unsigned char{ masked_value != 0 };
}

我不知道任何具有相同功能的 GCC 或 Clang 内在函数。如果需要,您可以改为从函数实现发出汇编指令,但是 bt 带有内存操作数的速度很慢,因此通常最好用纯 C++ 实现并让编译器做好。

更新:

在讨论了从内在函数发出的代码之后,很明显,之前提出的替换代码只涵盖了部分功能。特别是,内在函数允许在 *a 占用的内存之外索引位。以下实现也说明了这一点。

inline
unsigned char bittest(std::int32_t const *a, std::int32_t b)
{
    auto const bits{ reinterpret_cast<unsigned char const*>(a) };
    auto const value{ bits[b >> 3] };
    auto const mask{ (unsigned char)(1 << (b & 7)) };
    return (value & mask) != 0;
}

inline
unsigned char bittest64(std::int64_t const *a, std::int64_t b)
{
    auto const bits{ reinterpret_cast<unsigned char const*>(a) };
    auto const value{ bits[b >> 3] };
    auto const mask{ (unsigned char)(1 << (b & 7)) };
    return (value & mask) != 0;
}