如何使GCC像ICC一样生成向量指令?

时间:2018-05-22 10:32:43

标签: gcc vectorization icc

我在我的项目中一直使用ICC,ICC将很好地利用向量指令。最近我尝试使用GCC(版本5.5)编译相同的代码,但是在某些模块上,GCC的版本比ICC慢10倍。当我进行复数乘法等时会发生这种情况。

示例代码如下:

定义:

float *ptr1 = _mm_malloc(1280 , 64);
float *ptr2 = _mm_malloc(1280 , 64);
float complex *realptr1 = (float complex *)&ptr1[storageOffset];
float complex *realptr2 = (float complex *)&ptr2[storageOffset];

Pragma和编译器选项:

__assume_aligned(realptr1, 64);
__assume_aligned(realptr2, 64);
#pragma ivdep
#pragma vector aligned

for (j = 0; j < 512; j++) {
  float complex derSlot0 = realptr1[j] * realptr2[j];
  float complex derSlot1 = realptr1[j] + realptr2[j];
  realptr1[j] = derSlot0;
  realptr2[j] = derSlot1;
}

主要循环的ICC编译结果将如下:


    ..B1.6:                         # Preds ..B1.6 ..B1.5
                                    # Execution count [5.12e+02]
            vmovups   32(%r15,%rdx,8), %ymm9                        #35.29
            lea       (%r15,%rdx,8), %rax                           #37.5
            vmovups   (%rax), %ymm3                                 #35.29
            vaddps    32(%rbx,%rdx,8), %ymm9, %ymm11                #36.43
            vaddps    (%rbx,%rdx,8), %ymm3, %ymm5                   #36.43
            vmovshdup 32(%rbx,%rdx,8), %ymm6                        #35.43
            vshufps   $177, %ymm9, %ymm9, %ymm7                     #35.43
            vmulps    %ymm7, %ymm6, %ymm8                           #35.43
            vmovshdup (%rbx,%rdx,8), %ymm0                          #35.43
            vshufps   $177, %ymm3, %ymm3, %ymm1                     #35.43
            vmulps    %ymm1, %ymm0, %ymm2                           #35.43
            vmovsldup 32(%rbx,%rdx,8), %ymm10                       #35.43
            vfmaddsub213ps %ymm8, %ymm9, %ymm10                     #35.43
            vmovups   %ymm11, 32(%rbx,%rdx,8)                       #38.5
            vmovups   %ymm10, 32(%rax)                              #37.5
            vmovsldup (%rbx,%rdx,8), %ymm4                          #35.43
            vfmaddsub213ps %ymm2, %ymm3, %ymm4                      #35.43
            vmovups   %ymm5, (%rbx,%rdx,8)                          #38.5
            vmovups   %ymm4, (%rax)                                 #37.5
            addq      $8, %rdx                                      #32.3
            cmpq      $512, %rdx                                    #32.3
            jb        ..B1.6        # Prob 99%                      #32.3

用于icc的命令行是: icc -march = core-avx2 -S -fsource-asm -c test.c

对于海湾合作委员会,我已经做过的事情包括:替换" #pragma ivdep"用" #pragma GCC ivdep",替换" __ assume_aligned(realptr1,64);" with" realptr1 = __builtin_assume_aligned(realptr1,64);"

GCC的命令是: gcc -c -O2 -ftree-vectorize -mavx2 -g -Wa,-a,-ad gcctest.c

并且相同循环的结果是这样的:


     109                .L7:
     110 00d8 C5FA103B      vmovss  (%rbx), %xmm7
     111 00dc 4883C308      addq    $8, %rbx
     112 00e0 C5FA1073      vmovss  -4(%rbx), %xmm6
     112      FC
     113 00e5 4983C408      addq    $8, %r12
     114 00e9 C4C17A10      vmovss  -8(%r12), %xmm5
     114      6C24F8
     115 00f0 C4C17A10      vmovss  -4(%r12), %xmm4
     115      6424FC
     116                .LBB2:
     117                    .loc 1 35 0 discriminator 3
     118 00f7 C5F828C7      vmovaps %xmm7, %xmm0
     119 00fb C5F828CE      vmovaps %xmm6, %xmm1
     120 00ff C5FA1165      vmovss  %xmm4, -80(%rbp)
     120      B0
     121 0104 C5F828DC      vmovaps %xmm4, %xmm3
     122 0108 C5FA116D      vmovss  %xmm5, -76(%rbp)
     122      B4
     123 010d C5F828D5      vmovaps %xmm5, %xmm2
     124 0111 C5FA1175      vmovss  %xmm6, -72(%rbp)
     124      B8
     125 0116 C5FA117D      vmovss  %xmm7, -68(%rbp)
     125      BC
     126 011b E8000000      call    __mulsc3
     126      00
     127                .LVL7:
     128                    .loc 1 38 0 discriminator 3
     129 0120 C5FA107D      vmovss  -68(%rbp), %xmm7
     129      BC
     130 0125 C5FA106D      vmovss  -76(%rbp), %xmm5
     130      B4
     131 012a C5FA1075      vmovss  -72(%rbp), %xmm6
     131      B8
     132 012f C5D258EF      vaddss  %xmm7, %xmm5, %xmm5
     133 0133 C5FA1065      vmovss  -80(%rbp), %xmm4
     133      B0
     134                    .loc 1 35 0 discriminator 3
     135 0138 C5F9D645      vmovq   %xmm0, -56(%rbp)
     135      C8
     136                    .loc 1 38 0 discriminator 3
     137 013d C5DA58E6      vaddss  %xmm6, %xmm4, %xmm4
     138                    .loc 1 35 0 discriminator 3
     139 0141 C5FA1045      vmovss  -52(%rbp), %xmm0
     139      CC
     140                .LVL8:
     141                    .loc 1 37 0 discriminator 3
     142 0146 C5FA104D      vmovss  -56(%rbp), %xmm1
     142      C8
     143 014b C5FA114B      vmovss  %xmm1, -8(%rbx)
     143      F8
     144                .LVL9:
     145 0150 C5FA1143      vmovss  %xmm0, -4(%rbx)
     145      FC
     146                    .loc 1 38 0 discriminator 3
     147 0155 C4C17A11      vmovss  %xmm5, -8(%r12)
     147      6C24F8
     148 015c C4C17A11      vmovss  %xmm4, -4(%r12)
     148      6424FC
     149                .LBE2:
     150                    .loc 1 32 0 discriminator 3
     151 0163 4C39EB        cmpq    %r13, %rbx
     152 0166 0F856CFF      jne .L7
     152      FFFF

所以,我可以看到GCC使用某种向量指令,但它仍然不如ICC。

我的问题是,我能做更多的选择让GCC表现更好吗?

非常感谢。

1 个答案:

答案 0 :(得分:1)

您没有发布完整的代码进行测试,但您可以从添加

开始
 -ffast-math 

并可选择

-mfma

所以你或多或少会最终得到

  vmovaps ymm0, YMMWORD PTR [rbx+rax]
  vmovaps ymm3, YMMWORD PTR [r12+rax]
  vpermilps ymm2, ymm0, 177
  vpermilps ymm4, ymm3, 245
  vpermilps ymm1, ymm3, 160
  vmulps ymm2, ymm2, ymm4
  vmovaps ymm4, ymm0
  vfmsub132ps ymm4, ymm2, ymm1
  vfmadd132ps ymm1, ymm2, ymm0
  vaddps ymm0, ymm0, ymm3
  vmovaps YMMWORD PTR [rbx+rax], ymm0
  vblendps ymm1, ymm4, ymm1, 170
  vmovaps YMMWORD PTR [r12+rax], ymm1
  add rax, 32
  cmp rax, 4096
  jne .L6