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

标签 visual-c++ x86-64 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;
    }
}

在我的属性(property)解决方案中,我将“启用增强指令集”设置为“高级矢量扩展 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 都来自 C:\Windows\System32###.dll。

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

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

最佳答案

得到 4 而不是 59 听起来像 clang 将 _BitScanReverse64 实现为 63 - lzcnt。实际的 bsr 在 AMD 上很慢,所以是的,编译器想要编译不同指令固有的 BSR 是有原因的。

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

据我所知,所有具有 AVX2 的 CPU 也具有 BMI。如果您的 CPU 没有它,您不应该期望使用 /arch:AVX2 构建的可执行文件能够在您的 CPU 上正确运行。在这种情况下,故障模式不是非法指令,它是 lzcnt 作为 bsr 运行。

MSVC 通常不会优化内部函数,显然包括这种情况,所以它只是直接使用 bsr


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

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

它也不会为您将 CPUID 检查代码添加到您的可执行文件中。如果你想要那个,你自己写吧。这是 C++,它不会牵着你的手。


objective-c PU 选项

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 却没有。

关于visual-c++ - clang-cl 和 arch :avx2? 是否存在兼容性问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62493597/

相关文章:

windows - CFileDialog::OnInitDialog() 不调用

windows - Spectre/Meltdown 补丁导致 COM 方法返回 E_ACCESSDENIED

opencv - 卸载 winmmbase.dll visual studio 2015

visual-c++ - SAPI 5.3 语音转文本

c++ - 对不同的整数宽度使用 xadd

c++ - 使用 AVX2 和范围保存的按位类型转换

c - 负值与 rdi 寄存器的比较结果不正确

gcc - 无法从内核模式更改 CS 寄存器值。无效的操作码 : 0000

c - 使用 SIMD,我如何有条件地仅移动 alpha channel 值为 255 的像素?

sse - 将 32 位 int 中打包的 8 个 4 位值零扩展到 __m256i 的英特尔矢量指令?