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

标签 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];
        }
    }
}

它非常适合 Intel 编译器,并且 gcc >= 5,但 gcc < 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,但不会让它不受干扰地通过?是否有隐藏选项可以抑制此问题?

最佳答案

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

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

关于gcc - 使用 gcc < 5 抑制 AVX 内联汇编错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45358434/

相关文章:

gcc - fatal error : stdio. h:macOS 上没有这样的文件或目录

python - 为什么 pip 安装程序希望 gcc-4.2 成为 OS X Lion 中 gcc 编译器的名称?

c - 从内联汇编调用函数时针对符号重定位 R_X86_64_PC32

linux - 组装 NASM x86 - 简单堆栈项目

c++ - 在调用 print 之前清空 %al 寄存器

c - __builtin_avr_delay_cycles 实现说明

c++ - 使用 boost 编译时出错

危险类型转换的 C 编译器警告

c - x86 程序集中 '_emit 0Fh, _emit 31h' 是什么意思?

c++ - 动态库中的 libstdc++ 静态链接