提问人:xealits 提问时间:11/6/2023 最后编辑:Peter Cordesxealits 更新时间:11/6/2023 访问量:55
Clang中没有x86 BMI指令BLSI和BLSR的内部函数?
No intrinsics for x86 BMI instructions BLSI & BLSR in Clang?
问:
我想尝试一些 x86 BMI 集的内在因素。显示和我的 AMD Ryzen CPU 中。但是我无法让 clang 编译一些指令,特别是 BLSI 和 BLSR。看起来它们在 clang 的 bmiintrin.h
中不受支持。确实如此还是我错过了什么?一般来说,您是否需要为 Intel/AMD 的 LLVM 安装某种“插件”或类似的东西才能使用 CPU 特定的功能?在这种情况下,使用他们的构建工具会更好吗?grep bmi /proc/cpuinfo
bmi1
bmi2
在本文之后,我将使用 BLSI 或 BLSR unstructions 构建一个测试程序:
// 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);
}
}
它内置了打开所有 CPU 功能的功能:-march=native
clang -march=native test_bmi.c -o test_bmi
但是在组装中没有类似 - 的指令。查看 bliintrin.h 源代码,似乎实际上不支持 BLSI 和 BLSR 指令:blsi
objdump -d test_bmi
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 指令?这是故意的还是我错过了启用它们的东西?
答:
不需要特殊的内部函数,因为如果你只是在 C 中编写它们的行为,clang 就知道使用这些指令和其他类似的指令(包括 、 (!)、 、 、 和 (!) 等)。andn
bextr
popcnt
blsi
blsmsk
blsr
tzcnt
例如,你可以写
int my_blsi(int x)
{
return (x & -x);
}
并发现编译器将其转换为类似
my_blsi:
blsil %edi, %eax
ret
这种窥视孔分析非常强大,甚至可以识别(包括循环和位操作)和类似指令的常见实现。popcnt
tzcnt
因此,只需像往常一样编写代码,并针对支持您正在寻找的指令的目标架构进行编译。编译器将在适当的情况下自动使用它们。
请注意,您可能需要使用优化进行编译,才能触发这些优化;这可以解释您最初无法生成的原因。blsi
评论
blsi
blsi
i++
neg
sub
and
评论