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

No intrinsics for x86 BMI instructions BLSI & BLSR in Clang?

提问人:xealits 提问时间:11/6/2023 最后编辑:Peter Cordesxealits 更新时间:11/6/2023 访问量:55

问:

我想尝试一些 x86 BMI 集的内在因素。显示和我的 AMD Ryzen CPU 中。但是我无法让 clang 编译一些指令,特别是 BLSIBLSR。看起来它们在 clang 的 bmiintrin.h 中不受支持。确实如此还是我错过了什么?一般来说,您是否需要为 Intel/AMD 的 LLVM 安装某种“插件”或类似的东西才能使用 CPU 特定的功能?在这种情况下,使用他们的构建工具会更好吗?grep bmi /proc/cpuinfobmi1bmi2

本文之后,我将使用 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 指令:blsiobjdump -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 指令?这是故意的还是我错过了启用它们的东西?

程序集 x86 Clang 位操作 BMI

评论

2赞 Peter Cordes 11/6/2023
福兹的回答总体上是正确的。这是一个遗漏的优化错误,您应该报告 github.com/llvm/llvm-project/issues

答:

3赞 fuz 11/6/2023 #1

不需要特殊的内部函数,因为如果你只是在 C 中编写它们的行为,clang 就知道使用这些指令和其他类似的指令(包括 、 (!)、 、 、 和 (!) 等)。andnbextrpopcntblsiblsmskblsrtzcnt

例如,你可以写

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

并发现编译器将其转换为类似

my_blsi:
    blsil   %edi, %eax
    ret

这种窥视孔分析非常强大,甚至可以识别(包括循环和位操作)和类似指令的常见实现。popcnttzcnt

因此,只需像往常一样编写代码,并针对支持您正在寻找的指令的目标架构进行编译。编译器将在适当的情况下自动使用它们。

请注意,您可能需要使用优化进行编译,才能触发这些优化;这可以解释您最初无法生成的原因。blsi

评论

3赞 Peter Cordes 11/6/2023
godbolt.org/z/zeE86G1z5 表明 OP 是正确的,但 Clang 17 确实搞砸了,无法在此循环中使用。这种错过的优化也发生在较旧的 Clang 身上;我在 Godbolt 上尝试过的版本都没有使用.blsiblsi
0赞 fuz 11/6/2023
@PeterCordes令人着迷!对我来说,这似乎是一个错过的优化。
2赞 Peter Cordes 11/6/2023
也许环路计数器增量正在抛弃它,比如试图以某种方式利用它导致 IR 不再与 BLSI 窥视孔匹配?它实际上并没有使用 or ;哦,它数一个计数器,一个计数器下降!(和他们)/叹息。i++negsuband