assembly Clang中没有x86 BMI指令BLSI和BLSR的内部函数?

93ze6v8z  于 2023-11-19  发布在  其他
关注(0)|答案(1)|浏览(102)

我想尝试一些x86 BMI设置的intrinsic。grep bmi /proc/cpuinfo在我的AMD Ryzen CPU中显示bmi1bmi2。但我无法获得clang来编译一些指令,特别是BLSIBLSR。看起来它们在clang's bmiintrin.h中不受支持。这是真的吗?还是我错过了什么?一般来说,你是否需要安装某种来自Intel/AMD的LLVM“插件”或类似的东西来使用CPU特定的功能?在这种情况下,使用他们的构建工具更好吗?
this article之后,我用BLSI或BLSR构造了一个测试程序:

// test_bmi.c
#include <x86intrin.h>
// not #include <bmiintrin.h> - clang errors and asks for x86intrin.h
volatile unsigned long long result;

main() {
  ...
  for (unsigned long long i=0; i<max_count; i++) {
    result = _blsi_u64(i);
  }
}

字符串
它是用-march=native构建的,可以打开所有CPU功能:

clang -march=native test_bmi.c -o test_bmi


但是在objdump -d test_bmi汇编中没有类似blsi的指令。看看the bliintrin.h source,似乎实际上不支持BLSI和BLSR指令:

static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__blsi_u64(unsigned long long __X)
{
  return __X & -__X;
}


但是,例如,BEXTR在头文件中,它确实显示在objdump程序集中:

static __inline__ unsigned long long __DEFAULT_FN_ATTRS
__bextr_u64(unsigned long long __X, unsigned long long __Y)
{
  return __builtin_ia32_bextr_u64(__X, __Y);
}

$ objdump -d test_bmi | grep bextr
    12c5:  c4 e2 f0 f7 c0         bextr  %rcx,%rax,%rax


这是否意味着clang并不真正支持BLSI和BLSR指令?这是故意的,还是我错过了一些东西来启用它们?

k5ifujac

k5ifujac1#

不需要特殊的intrinsic,因为clang知道使用这些指令和其他类似的指令(包括andnbextrpopcnt(!),blsiblsmskblsrtzcnt(!)等),如果你只是在C中编写它们的行为。
例如,你可以写

int my_blsi(int x)
{
    return (x & -x);
}

字符串
编译器会把它变成

my_blsi:
    blsil   %edi, %eax
    ret


这种窥视孔分析非常强大,甚至可以识别popcnt(包括循环和位操作),tzcnt和类似指令的常见实现。
因此,只需像平常一样编写代码,并为支持您正在寻找的指令的目标体系结构进行编译。编译器将在适当的地方自动使用它们。
请注意,您可能需要使用优化进行编译,以使这些优化触发;这可以解释您最初未能生成blsi的原因。

相关问题