使用gcc<抑制AVX内联汇编错误5

时间:2017-07-27 18:26:32

标签: gcc assembly

我有一个AVX内核我写的做复杂的共轭乘法:

__attribute__((noinline))
static __attribute__((target("avx"))) void asm_vcmulcc(
    cfloat* __restrict__ cc, const cfloat* __restrict__ aa, const cfloat* __restrict__ bb, ssize_t size) {

    ssize_t iters = size/4;
    ssize_t rem   = size-iters*4;

    __asm__(
        ".section .rodata # constant section\n\t"
        ".align 32        # 32 byte alignment\n\t"
        "LC%=:\n\t" 
        "     .long 0x80000000\n\t"
        "     .long 0x80000000\n\t"
        "     .long 0x80000000\n\t"
        "     .long 0x80000000\n\t"
        "     .long 0x80000000\n\t"
        "     .long 0x80000000\n\t"
        "     .long 0x80000000\n\t"
        "     .long 0x80000000\n\t"
        ""
        ".text\n\t"
        "     vmovaps   LC%=(%%rip), %%ymm4\n\t"
        "     xorl      %%eax,  %%eax\n\t"
        ""
        ".p2align 4\n\t"
        "LOOP%=:\n\t"
        "     vmovups   (%[bb],%%rax,1), %%ymm3\n\t"
        "     vmovups   (%[aa],%%rax,1), %%ymm1\n\t"
        "     vpermilps $0xa0,  %%ymm1,  %%ymm2\n\t"
        "     vpermilps $0xf5,  %%ymm1,  %%ymm0\n\t"               
        "     vmulps    %%ymm3, %%ymm2,  %%ymm2\n\t"
        "     vxorps    %%ymm4, %%ymm0,  %%ymm0\n\t"
        "     vpermilps $0xb1,  %%ymm3,  %%ymm3\n\t"
        "     vmulps    %%ymm3, %%ymm0,  %%ymm0\n\t"
        "     vaddsubps %%ymm0, %%ymm2,  %%ymm0\n\t"
        "     vmovups   %%ymm0, (%[cc],%%rax,1)\n\t"
        "     addq      $32,      %%rax\n\t"
        "     cmpq      %[bytes], %%rax\n\t"
        "     jl        LOOP%=\n\t"
        :
        : [aa] "r" (aa), [bb] "r" (bb), [cc] "r" (cc), [bytes] "r" (iters*4*sizeof(cfloat))
        : "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "rax", "memory"
    );

    if (rem > 0) {
        aa += iters*4;
        bb += iters*4;
        cc += iters*4;

        for (ssize_t ii=0; ii < rem; ii++) {
            cc[ii] = conj(aa[ii])*bb[ii];
        }
    }
}

适用于英特尔编译器,gcc&gt; = 5,但gcc&lt; 5个错误输出(这是g ++ 4.8.5):

> g++ -std=c++0x -I. -c -mavx lib.cc -O3 -o lib.o
lib.cc: In function ‘void avx_vcmulcc(prelude::{anonymous}::cfloat*, const cfloat*, const cfloat*, int)’:
lib.cc:80:6: error: unknown register name ‘ymm4’ in ‘asm’
     );
      ^
lib.cc:80:6: error: unknown register name ‘ymm3’ in ‘asm’
lib.cc:80:6: error: unknown register name ‘ymm2’ in ‘asm’
lib.cc:80:6: error: unknown register name ‘ymm1’ in ‘asm’
lib.cc:80:6: error: unknown register name ‘ymm0’ in ‘asm’

有或没有-mavx选项。显然,允许编译器发出AVX,但是不会让它通过unmolested?是否有一个隐藏的选项来抑制这个?

1 个答案:

答案 0 :(得分:2)

您需要指定XMM寄存器,因为从编译器的角度来看,这些是被破坏的寄存器,因为编译器对YMM寄存器一无所知。您应该添加一个编译器条件并在支持它们的编译器上使用YMM寄存器,因为理论上可以使用XMM寄存器而不会干扰仅YMM寄存器部分(使用SSE2指令),未来的GCC版本可能会使用该信息(虽然这似乎不太可能)。 this document on transition penalities中提到了这一点。更多详情请见Intel Advanced Vector Extensions Programming Reference

请注意,您可以将.long数组定义为具有used属性的静态数组,并从内联程序集引用该数组。如果内联汇编语句被编译器复制或多次使用,这将避免重复常量。 (或者,您可以为数组使用m输入操作数,并删除数组上的used属性,这也有利于它在大内存模型中正常工作。)