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



我使用的是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;
}
}

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

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

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

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

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

获得 4 而不是 59 听起来像是 clang 实现_BitScanReverse64作为63 - 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,所以这解释了你的结果。

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

它也不会将 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上。 (这实际上比63-lzcnt更适合英特尔 CPU(。 我认为MSVC的/arch:AVX2类似于-march=haswell,如果它也启用FMA指令。

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

但是GCC和clang-march=native启用计算机支持的所有指令集。 同样重要的是,设置适合您计算机的调整选项。 例如,不要担心在 AMD CPU 或较旧的英特尔上制作速度较慢的代码,只需制作对您的 CPU 有益的 asm。

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

最新更新