clang-cl 和 arch:avx2 是否存在兼容性问题?

pol*_*iz4 2 x86-64 visual-c++ avx2 clang-cl

我使用的是 Windows 10、Visual Studio 2019、平台:x64,并且在单文件 Visual Studio 解决方案中具有以下测试脚本:

#include <iostream>
#include <intrin.h>
using namespace std;

int main() {
    unsigned __int64 mask = 0x0fffffffffffffff; //1152921504606846975;
    unsigned long index;

    _BitScanReverse64(&index, mask);
    if (index != 59) {
        cout << "Fails!" << endl;
        return EXIT_FAILURE;
    }
    else {
        cout << "Success!" << endl;
        return EXIT_SUCCESS;
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的属性解决方案中,我将“启用增强指令集”设置为“高级矢量扩展 2 (/arch:AVX2)”。当使用 msvc 编译(将“平台工具集”设置为“Visual Studio 2019 (v142)”)时,代码返回 EXIT_SUCCESS,但是当使用 clang-cl 编译(将“平台工具集”设置为“LLVM (clang-cl)”)时,我得到退出失败。调试 clang-cl 运行时,index 的值为 4,而它应该是 59。这表明 clang-cl 正在以与 MSVC 相反的方向读取位。

当我将“启用增强指令集”设置为“未设置”时,情况并非如此。在这种情况下,MSVC 和 clang-cl 都返回 EXIT_SUCCESS。

在所有情况下,所有 dll 都会加载并显示在“调试输出”窗口中,这些 dll 来自 C:\Windows\System32###.dll。

有人理解这种行为吗?我将不胜感激这里的任何见解。

编辑:我之前没有提到:我用 IntelCore i7-3930K CPU @3.20GHz 编译了这个。

Pet*_*des 6

得到 4 而不是 59 听起来像是 clang 实现_BitScanReverse6463 - lzcnt. AMD 上的实际速度bsr很慢,所以是的,编译器有理由希望将 BSR 内在编译为不同的指令。

但随后您在实际上不支持 BMI 的计算机上运行可执行文件,因此lzcnt解码为rep bsr=bsr,给出前导零计数而不是最高设置位的位索引。

AFAIK,所有具有 AVX2 的 CPU 也具有 BMI。如果您的 CPU 没有这个功能,您就不应期望构建的可执行文件/arch:AVX2能够在您的 CPU 上正确运行。在这种情况下,故障模式不是非法指令,而是lzcntbsr.

MSVC一般不会优化内在函数,显然包括这种情况,所以它只是bsr直接使用。


更新:i7-3930K是 SandyBridge-E。它没有 AVX2,所以这可以解释你的结果。

当您告诉 clang-cl 在非 AVX2 计算机上构建 AVX2 可执行文件时,它不会出错。其用例是在一台机器上编译以创建在不同机器上运行的可执行文件。

它还不会为您将 CPUID 检查代码添加到您的可执行文件中。如果你想要的话,就自己写吧。这是C++,它握不住你的手。


目标CPU选项

MSVC 风格的/arch选项比普通的 GCC/clang 风格受到更多限制。没有像SSE4.1这样针对不同级别的SSE;它直接跳转到 AVX。

此外,/arch:AVX2显然意味着 BMI1/2,即使它们是具有不同 CPUID 功能位的不同指令集。例如,在内核代码中,您可能需要整数 BMI 指令,但不需要接触 XMM/YMM 寄存器的 SIMD 指令。

clang -O3 -mavx2不会启用-mbmi. 您通常会希望如此,但如果您未能同时启用 BMI,那么 clang 将一直使用bsr。(对于 Intel CPU 来说,这实际上比 更好63-lzcnt)。我认为 MSVC 的 /arch:AVX2 类似于-march=haswell,如果它也启用 FMA 指令。

MSVC 中没有任何内容支持优化二进制文件以在您构建它们的计算机上运行。这是有道理的,它是为软件开发的闭源二进制分发模型而设计的。

但是 GCC 和 clang 必须-march=native启用您的计算机支持的所有指令集。同样重要的是,设置适合您的计算机的调整选项。例如,不必担心编写的代码在 AMD CPU 或较旧的 Intel 上会很慢,只需编写适合您的CPU 的 asm 即可。

TL:DR:clang-cl 中的 CPU 选择选项非常粗略,将非 SIMD 扩展与某种级别的 AVX 混在一起。这就是为什么/arch:AVX2启用整数 BMI 扩展,而clang -mavx2不会启用。

  • @polortiz40:那是 Sandybridge,已经有 2 代了,已经没有 BMI1/2 或 AVX2/FMA 了。你只有AVX1。查看我的更新。 (2认同)