如何指示MS Visual C ++编译器使用未初始化的__m512i寄存器

问题描述 投票:3回答:1

如何指示Visual C ++编译器(1926)使用未初始化的__m512i寄存器。在以下代码段中,计算出not(or(A,B)),与dummy的内容无关。

__m512i dummy;
const __m512i n8 = _mm512_ternarylogic_epi64(dummy, A, B, 0x11);

以某种方式,编译器认为寄存器需要具有某些内容,(没有),并且为zmm0生成了昂贵且不必要的内存引用:

62 F1 7E 48 6F 45 00 vmovdqu32   zmm0,zmmword ptr [rbp]  
62 F3 DD 48 25 C5 11 vpternlogq  zmm0,zmm4,zmm5,11h  

ICC 19.0.1理解这种情况,不生成vmovdqu32

我尝试了什么:用0初始化dummy替换为:vmovdqu32

C5 F1 EF C9          vpxor       xmm1,xmm1,xmm1

这仍然会给出不必要的指令和停顿。

因此,问题:如何指示Visual C ++编译器执行与Intel编译器相同的操作?只是不要初始化虚拟寄存器。

c++ visual-c++ intrinsics micro-optimization avx512
1个回答
2
投票

和档位

xor-zeroing is dependency breaking。从字面上讲,它也与当前的Intel CPU上的NOP一样便宜,并且避免了将此dep链耦合到另一个链的输出依赖性风险。它不会造成停顿(间接造成的除外,例如由于I缓存未命中),但这可能浪费一个前端吞吐量的融合域uop。


如果此后AB无效,则使用其中一个作为虚拟输入,像这样

__m512i nor_A(__m512i A, __m512i B) {
    return _mm512_ternarylogic_epi64(A, A, B, 0x11);
}

[未内联时,因此输入的regs之后便失效,并且它必须返回与它收到的A相同的reg,所有4个主要的x86编译器都为这种简单情况提供了理想的代码。 (我想使用第一个输入将立即数优化为5而不是0x11。)

; MSVC 19.24 -O2 -arch:AVX512 -Gv    (vectorcall calling convention)
# gcc10/clang10/ICC19 -O3 -march=skylake-avx512
nor_A:
        vpternlogq      zmm0, zmm0, zmm1, 17
        ret

或者如果您是在循环中使用它,则可以通过将目标用作第一个输入来有意创建循环承载的dep链。在循环外声明向量。如果要在包装函数中使用ternlog,则需要将对该向量的引用传递到该函数中,以使此工作有效。


如果您想冒一个错误的依赖关系,_mm512_undefined_epi32()是您想要的最大希望]。它安全地表达您想要的内容(任意寄存器),同时避免未定义行为读取未初始化的C变量。 (不,IDK,为什么英特尔认为_mm512_undefined_epi32()epi32更像si512更有意义。它没有被掩盖的版本!)

ICC将其编译为零个额外指令。但是,Clang,GCC和MSVC会将目标寄存器异或为零,如果它们内部确实不支持未定义的输入,则可以将其实现为_mm_undefined_si128()_mm512_setzero_si512

我还在实际的UB中包括了版本; ICC和clang在此处执行您想要的操作,选择Godbolt作为虚拟输入。

zmm0

MSVC 19.24 __m512i nor_undef(__m512i A, __m512i B) { return _mm512_ternarylogic_epi64(_mm512_undefined_epi32(), A, B, 0x11); } -不太好,但是基本上还不错,因此相同的源代码可以编译成您想要的ICC内容,而不会在任何地方造成麻烦。

-O2 -arch:AVX512 -Gv

GCC 10.1:

__m512i nor_undef(__m512i,__m512i) PROC             ; nor_undef, COMDAT
    vpxor   xmm2, xmm2, xmm2
    vpternlogq zmm2, zmm0, zmm1, 17
    vmovdqu32 zmm0, zmm2
    ret     0

Clang 10.0

nor_undef:
    vmovdqa64       zmm2, zmm0
    vpxor   xmm0, xmm0, xmm0
    vpternlogq      zmm0, zmm2, zmm1, 17
    ret

ICC 19.0.1

nor_undef:
    vpxor   xmm2, xmm2, xmm2
    vpternlogq      zmm0, zmm2, zmm1, 5
    ret
© www.soinside.com 2019 - 2024. All rights reserved.