热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

为什么GCC在我的机器上创建额外的组装说明?

如何解决《为什么GCC在我的机器上创建额外的组装说明?》经验,为你挑选了1个好方法。

自从我开始使用SSE / AVX内部函数以来已经有一段时间了。我最近开始为矩阵转置编写标题。我使用了很多if constexpr分支,以便编译器始终根据某些模板参数来选择最佳指令集。现在,我想通过使用来检查本地反汇编来检查是否一切正常objdump。使用Clang时,我得到一个清晰的输出,该输出基本上只包含与所使用的内在函数相对应的汇编指令。但是,如果我使用GCC,则在使用其他说明时反汇编会很is肿。快速检查一下Godbolt,我发现GCC拆卸中的这些多余说明不应该存在。

这是一个小例子:

#include 
#include 

std::array<__m256, 1> Test(std::array<__m256, 1> a)
{
    std::array<__m256, 1> b;

    b[0] = _mm256_unpacklo_ps(a[0], a[0]);
    return b;
}

我编译-march=native -Wall -Wextra -Wpedantic -pthread -O3 -DNDEBUG -std=gnu++1z。然后我objdump -S -Mintel libassembly.a > libassembly.dump在目标文件上使用。对于Clang(6.0.0),结果是:

In archive libassembly.a:

libAssembly.cpp.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <_Z4TestSt5arrayIDv8_fLm1EE>:
   0:   c4 e3 7d 04 c0 50       vpermilps ymm0,ymm0,0x50
   6:   c3                      ret    

这与Godbolt返回的结果相同:Godbolt-Clang 6.0.0

对于GCC(7.4),输出为

In archive libassembly.a:

libAssembly.cpp.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <_Z4TestSt5arrayIDv8_fLm1EE>:
   0:   4c 8d 54 24 08          lea    r10,[rsp+0x8]
   5:   48 83 e4 e0             and    rsp,0xffffffffffffffe0
   9:   c5 fc 14 c0             vunpcklps ymm0,ymm0,ymm0
   d:   41 ff 72 f8             push   QWORD PTR [r10-0x8]
  11:   55                      push   rbp
  12:   48 89 e5                mov    rbp,rsp
  15:   41 52                   push   r10
  17:   48 83 ec 28             sub    rsp,0x28
  1b:   64 48 8b 04 25 28 00    mov    rax,QWORD PTR fs:0x28
  22:   00 00 
  24:   48 89 45 e8             mov    QWORD PTR [rbp-0x18],rax
  28:   31 c0                   xor    eax,eax
  2a:   48 8b 45 e8             mov    rax,QWORD PTR [rbp-0x18]
  2e:   64 48 33 04 25 28 00    xor    rax,QWORD PTR fs:0x28
  35:   00 00 
  37:   75 0c                   jne    45 <_Z4TestSt5arrayIDv8_fLm1EE+0x45>
  39:   48 83 c4 28             add    rsp,0x28
  3d:   41 5a                   pop    r10
  3f:   5d                      pop    rbp
  40:   49 8d 62 f8             lea    rsp,[r10-0x8]
  44:   c3                      ret    
  45:   c5 f8 77                vzeroupper 
  48:   e8 00 00 00 00          call   4d <_Z4TestSt5arrayIDv8_fLm1EE+0x4d>

如您所见,还有很多其他说明。与此相反,Godbolt不包括所有这些额外说明:Godbolt-GCC 7.4

那么这是怎么回事?我刚刚开始学习汇编,所以对于有汇编经验的人来说也许是很清楚的,但是我有点困惑为什么GCC在我的机器上创建这些额外的指令。

问候和预先感谢。

编辑

为了避免进一步的混乱,我只是使用以下命令进行了编译:

gcc-7 -I/usr/local/include -O3 -march=native -Wall -Wextra -Wpedantic -pthread -std=gnu++1z -o test.o -c //libAssembly.cpp

输出保持不变。我不确定这是否相关,但是会生成警告: warning: ignoring attributes on template argument ‘__m256 {aka __vector(8) float}’ [-Wignored-attributes]

通常,我不会发出此警告,这应该不是问题:

GCC警告的含义:忽略模板参数上的属性(-Wignored-attributes)

处理器是 Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz

这是gcc -v

gcc-7 -v
Using built-in specs.
COLLECT_GCC=gcc-7
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.4.0-1ubuntu1~18.04.1' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1) 

Peter Cordes.. 8

使用 -fno-stack-protector


您本地的GCC默认为,-fstack-protector-strong但Godbolt的GCC安装没有。

mov rax,QWORD PTR fs:0x28是讲故事的线索 ; GCC将其堆栈COOKIE保持不变,这fs:40就是aka的线程本地存储fs:0x28。在call之后的retcall __stack_chk_fail(但你拆开一个.o不使用objdump -dr,以显示迁移,所以占位符+0偏移只是看着这样的函数中仍然是一个目标)。

由于您具有数组(或包含数组的类),因此即使堆栈大小是编译时常量,堆栈保护器也会生效。因此,您将获得存储堆栈COOKIE的代码,然后对其进行检查并在堆栈溢出时分支。(即使此MVCE中的大小为1的数组也足以触发它。)

在堆栈上以32个字节的对齐方式(for __m256)需要32个字节的对齐方式,并且您的GCC比GCC8老,因此您得到了笨拙的堆栈对齐代码,该代码构建了包含返回地址的堆栈帧的完整副本。 为扩展堆栈变量的对齐而生成的程序集 (要清楚,GCC​​8仍然在此处对齐堆栈,只是在上面浪费了更少的指令。)

这几乎是一个错过的优化;gcc从未真正溢出或重新加载到这些阵列,因此它可以像优化堆栈一样将它们优化掉,就像没有堆栈保护器一样。

最近的GCC在更多情况下为对齐的局部变量优化了内存之后,更擅长优化堆栈的对齐方式,但这一直是AVX代码中永久遗漏的优化。幸运的是,在一个循环函数中,成本几乎可以忽略不计。只要小助手可以内联即可。


在Godbolt上进行编译可-fstack-protector-strong复制您的输出。 较新的GCC(包括当前的主干10之前的版本)仍然没有进行优化,但是堆栈对齐的开销较少,因为它仅使用RBP作为帧指针并对齐RSP,然后引用相对于对齐的RSP的局部变量。它仍然检查堆栈COOKIE(在存储和检查之间没有任何说明)。

在您的桌面上,使用-fno-stack-protector进行编译应该会很好。



1> Peter Cordes..:

使用 -fno-stack-protector


您本地的GCC默认为,-fstack-protector-strong但Godbolt的GCC安装没有。

mov rax,QWORD PTR fs:0x28是讲故事的线索 ; GCC将其堆栈COOKIE保持不变,这fs:40就是aka的线程本地存储fs:0x28。在call之后的retcall __stack_chk_fail(但你拆开一个.o不使用objdump -dr,以显示迁移,所以占位符+0偏移只是看着这样的函数中仍然是一个目标)。

由于您具有数组(或包含数组的类),因此即使堆栈大小是编译时常量,堆栈保护器也会生效。因此,您将获得存储堆栈COOKIE的代码,然后对其进行检查并在堆栈溢出时分支。(即使此MVCE中的大小为1的数组也足以触发它。)

在堆栈上以32个字节的对齐方式(for __m256)需要32个字节的对齐方式,并且您的GCC比GCC8老,因此您得到了笨拙的堆栈对齐代码,该代码构建了包含返回地址的堆栈帧的完整副本。 为扩展堆栈变量的对齐而生成的程序集 (要清楚,GCC​​8仍然在此处对齐堆栈,只是在上面浪费了更少的指令。)

这几乎是一个错过的优化;gcc从未真正溢出或重新加载到这些阵列,因此它可以像优化堆栈一样将它们优化掉,就像没有堆栈保护器一样。

最近的GCC在更多情况下为对齐的局部变量优化了内存之后,更擅长优化堆栈的对齐方式,但这一直是AVX代码中永久遗漏的优化。幸运的是,在一个循环函数中,成本几乎可以忽略不计。只要小助手可以内联即可。


在Godbolt上进行编译可-fstack-protector-strong复制您的输出。 较新的GCC(包括当前的主干10之前的版本)仍然没有进行优化,但是堆栈对齐的开销较少,因为它仅使用RBP作为帧指针并对齐RSP,然后引用相对于对齐的RSP的局部变量。它仍然检查堆栈COOKIE(在存储和检查之间没有任何说明)。

在您的桌面上,使用-fno-stack-protector进行编译应该会很好。


推荐阅读
  • 学习SLAM的女生,很酷
    本文介绍了学习SLAM的女生的故事,她们选择SLAM作为研究方向,面临各种学习挑战,但坚持不懈,最终获得成功。文章鼓励未来想走科研道路的女生勇敢追求自己的梦想,同时提到了一位正在英国攻读硕士学位的女生与SLAM结缘的经历。 ... [详细]
  • 本文介绍了Linux系统中正则表达式的基础知识,包括正则表达式的简介、字符分类、普通字符和元字符的区别,以及在学习过程中需要注意的事项。同时提醒读者要注意正则表达式与通配符的区别,并给出了使用正则表达式时的一些建议。本文适合初学者了解Linux系统中的正则表达式,并提供了学习的参考资料。 ... [详细]
  • Ubuntu 9.04中安装谷歌Chromium浏览器及使用体验[图文]
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • Ubuntu安装常用软件详细步骤
    目录1.GoogleChrome浏览器2.搜狗拼音输入法3.Pycharm4.Clion5.其他软件1.GoogleChrome浏览器通过直接下载安装GoogleChro ... [详细]
  • 2016 linux发行版排行_灵越7590 安装 linux (manjarognome)
    RT之前做了一次灵越7590黑苹果炒作业的文章,希望能够分享给更多不想折腾的人。kawauso:教你如何给灵越7590黑苹果抄作业​zhuanlan.z ... [详细]
  • 本文介绍了在Ubuntu系统中清理残余配置文件和无用内容的方法,包括清理残余配置文件、清理下载缓存包、清理不再需要的包、清理无用的语言文件和清理无用的翻译内容。通过这些清理操作可以节省硬盘空间,提高系统的运行效率。 ... [详细]
  • 本文介绍了在Ubuntu 11.10 x64环境下安装Android开发环境的步骤,并提供了解决常见问题的方法。其中包括安装Eclipse的ADT插件、解决缺少GEF插件的问题以及解决无法找到'userdata.img'文件的问题。此外,还提供了相关插件和系统镜像的下载链接。 ... [详细]
  • 像跟踪分布式服务调用那样跟踪Go函数调用链 | Gopher Daily (2020.12.07) ʕ◔ϖ◔ʔ
    每日一谚:“Acacheisjustamemoryleakyouhaven’tmetyet.”—Mr.RogersGo技术专栏“改善Go语⾔编程质量的50个有效实践” ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • 成功安装Sabayon Linux在thinkpad X60上的经验分享
    本文分享了作者在国庆期间在thinkpad X60上成功安装Sabayon Linux的经验。通过修改CHOST和执行emerge命令,作者顺利完成了安装过程。Sabayon Linux是一个基于Gentoo Linux的发行版,可以将电脑快速转变为一个功能强大的系统。除了作为一个live DVD使用外,Sabayon Linux还可以被安装在硬盘上,方便用户使用。 ... [详细]
  • STM32与FPGA的对比及学习建议
    本文对比了野火STM32F103指南针板和Xilinx的PYNQ-Z2板(ZYNQ-7020),介绍了野火STM32F103指南针板的学习资料和讲解视频的详细程度,建议初学者学习野火的资料。同时,介绍了STM32开发所用的Keil程序和C指针的重要性。对于ZYNQ-7020的开发,提到了其自带的Linux、Ubuntu18.4系统以及使用SD卡烧入镜像的方法。 ... [详细]
  • 我有一个vim默认安装在Linux上,在一个系统上有vt52终端仿真器和unicode功能。Vim不会接受换行一切都工作正常,直到今天,当 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了2D阵列选择排序相关的知识,希望对你有一定的参考价值。所以 ... [详细]
  • [更新幻灯]1剔除“伪创新”和“无领域”的领域驱动设计
    如果有人不了解人体的内部结构,就自称医生,声称自己能给人开腹割掉发炎的阑尾,甚至还能开胸给冠心病人做心脏搭桥,你信吗 ... [详细]
author-avatar
嘟嘟2502860271_460
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有