首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >gcc在哥德螺栓上的怪异自动矢量化研究

gcc在哥德螺栓上的怪异自动矢量化研究
EN

Stack Overflow用户
提问于 2022-04-13 13:50:19
回答 1查看 143关注 0票数 1

我被自动矢量化结果搞糊涂了。以下代码addtest.c

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>

#define ELEMS 1024

int
main()
{
  float data1[ELEMS], data2[ELEMS];
  for (int i = 0; i < ELEMS; i++) {
    data1[i] = drand48();
    data2[i] = drand48();
  }
  for (int i = 0; i < ELEMS; i++)
    data1[i] += data2[i];
  printf("%g\n", data1[ELEMS-1]); 
  return 0;
}

是用gcc 11.1.0编译的

代码语言:javascript
复制
gcc-11 -O3 -march=haswell -masm=intel -save-temps -o addtest addtest.c

而加法循环被自动矢量化为

代码语言:javascript
复制
.L3:
    vmovaps ymm1, YMMWORD PTR [r12]
    vaddps  ymm0, ymm1, YMMWORD PTR [rax]
    add r12, 32
    add rax, 32
    vmovaps YMMWORD PTR -32[r12], ymm0
    cmp r12, r13
    jne .L3

这一点很清楚:从data1加载,从data2加载和添加,存储到data1,在中间提前索引。

如果我将相同的代码传递给https://godbolt.org,选择x86-64 gcc-11.1和options -O3 -march=haswell,我将得到以下汇编代码:

代码语言:javascript
复制
.L3:
        vmovaps ymm1, YMMWORD PTR [rbp-4112+rax]
        vaddps  ymm0, ymm1, YMMWORD PTR [rbp-8208+rax]
        vmovaps YMMWORD PTR [rbp-8240], ymm1
        vmovaps YMMWORD PTR [rbp-8208+rax], ymm0
        add     rax, 32
        cmp     rax, 4096
        jne     .L3

一个令人惊讶的事情是不同的地址处理,但让我完全困惑的是[rbp-8240]的附加存储。据我所知,这个位置再也不用了。

如果我选择了gcc 7.5,多余的商店消失了(但从8.1以上,它就产生了)。

所以我的问题是:

  • 为什么我的编译器和戈德波特(不同的地址处理,多余的存储)之间有区别?
  • 多余的商店是做什么的?

非常感谢你的帮助!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-14 02:17:01

差异制造者是-fpie**,,默认情况下,大多数发行版都是,而不是哥德波特。**这没有多大意义,但编译器是复杂的机器,不是“智能”的。

它也不特定于-march=haswell或AVX;同样的区别只发生在-O3上。

与发行版相比,天栓为GCC配置了比发行版更简单的选项,例如,没有默认饼,也没有-fstack-protector-strong。若要在本地匹配“天栓”,请至少使用-fno-pie -no-pie -fno-stack-protector。也许还有其他我忘了的。

IDK为什么这会触发或避免漏掉的优化,但我可以确认它是在我的Arch /Linux系统上使用GCC 11.1实现的。

gcc -O3 -march=haswell -fno-stack-protector -fno-pie的局部

(和-masm=intel -S -o- vec.c | less)它与哥德波特相匹配:

代码语言:javascript
复制
.L3:
        vmovaps ymm1, YMMWORD PTR [rbp-4112+rax]
        vaddps  ymm0, ymm1, YMMWORD PTR [rbp-8208+rax]
        vmovaps YMMWORD PTR [rbp-8240], ymm1
        vmovaps YMMWORD PTR [rbp-8208+rax], ymm0
        add     rax, 32
        cmp     rax, 4096
        jne     .L3

但是使用-O3 -march=haswell中配置发行版的GCC默认设置

代码语言:javascript
复制
.L3:
        vmovaps ymm1, YMMWORD PTR [r12]
        vaddps  ymm0, ymm1, YMMWORD PTR [rax]
        add     r12, 32
        add     rax, 32
        vmovaps YMMWORD PTR -32[r12], ymm0
        cmp     r12, r13
        jne     .L3

在没有-march=haswell的情况下,也会发生同样的丢失-opt;我们在循环中将movaps XMMWORD PTR [rsp], xmm1存储到一个固定地址。(由于GCC不需要对齐堆栈来溢出32字节的向量,所以它没有使用RBP作为帧指针。)

没有明显的原因,使用-fpie 关于戈德波特编译器浏览器 的让GCC使用两个指针增量,而不是索引寻址模式,同时也避免了冗余存储。(在本地制作相同的asm )。-fpie强迫GCC对静态存储中的数组执行此操作(因为[arr + rax]将要求符号地址作为32位绝对值:在x86-64 Linux中不再允许32位绝对地址?)。

您可以并且应该在 GCC的布奇拉 上使用关键字“错过优化”.报告这一点。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71858658

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档