gcc 5.3 with -O3 -mavx -mtune=haswellfor x86-64使得代码处理可能错位的代码变得非常笨重,例如:
// convenient simple example of compiler input
// I'm not actually interested in this for any real program
void floatmul(float *a) {
for (int i=0; i<1024 ; i++)
a[i] *= 2;
}
Run Code Online (Sandbox Code Playgroud)
clang使用未对齐的加载/存储指令,但是gcc执行标量intro/outro和对齐的向量循环:它剥离了第一个最多7个未对齐的迭代,将其完全展开为一个序列
vmovss xmm0, DWORD PTR [rdi]
vaddss xmm0, xmm0, xmm0 ; multiply by two
vmovss DWORD PTR [rdi], xmm0
cmp eax, 1
je .L13
vmovss xmm0, DWORD PTR [rdi+4]
vaddss xmm0, xmm0, xmm0
vmovss …Run Code Online (Sandbox Code Playgroud) movemask指令采用__m256i并返回int32,其中每个位(取决于输入向量元素类型的前4位,8位或所有32位)是相应向量元素的最高有效位.
我想做反过来:取一个32(其中只有4,8或32个最低有效位有意义),并获得__m256i,其中每个int8,int32或int64大小的块的最高有效位设置为原始位.
基本上,我想从压缩的位掩码转到可被其他AVX2指令(例如maskstore,maskload,mask_gather)用作掩码的位掩码.
我无法快速找到这样做的指令,所以我在这里问.如果没有一条具有该功能的指令,您是否可以想到一个聪明的黑客,只需很少的指令即可实现这一点?
我目前的方法是使用256元素查找表.我想在一个没有其他事情发生的循环中使用这个操作来加速它.注意,我对长多指令序列或实现此操作的小循环不太感兴趣.
我在 C/C++ 代码中明确使用了英特尔 SIMD 内在扩展。为了编译代码,我需要在命令行上指定 -mavx、-mavx512 或类似的内容。我对这一切都很满意。
然而,从阅读 gcc 手册页来看,并不清楚这些命令行标志是否也告诉 gcc 编译器尝试使用英特尔 SIMD 指令自动矢量化 C/C++ 代码。有人知道情况是否如此吗?-mavx 标志只是允许您手动将 SIMD 内在函数插入代码中,还是还告诉编译器在编译 C/C++ 代码时使用 SIMD 指令?
我想知道编译器如何处理内部函数。
如果使用 SSE2 Intrinsics (Using #include <emmintrin.h>) 并使用-mavx标志进行编译。编译器会生成什么?它会生成 AVX 或 SSE 代码吗?
如果使用 AVX2 Intrinsics (Using #include <immintrin.h>) 并使用-msse2标志进行编译。编译器会生成什么?它会生成 SSE Only 或 AVX 代码吗?
编译器如何处理内部函数?
如果使用 Intrinsics,它是否可以帮助编译器理解循环中的依赖关系以实现更好的矢量化?
例如,这里发生了什么 - https://godbolt.org/z/Y4J5OA(或https://godbolt.org/z/LZOJ2K)?
查看全部 3 个窗格。
我正在尝试构建具有不同 CPU 功能(SSE4 和 AVX2)的相同功能的各种版本。
我正在使用 SSE Intrinsics 编写相同的版本,并且使用 AVX Intrinsics 编写一次。
假设他们的名字MyFunSSE()是 和MyFunAVX()。两者都在同一个文件中。
如何让编译器(相同的方法适用于 MSVC、GCC 和 ICC)仅使用各自的函数来构建它们?