为什么在使用 -O0 编译目标文件时,GCC 不使用 LTO 进行函数死代码消除?

2023-12-14

Example:

notmain.c

int __attribute__ ((noinline)) notmain(int i) {
    return i + 1;
}

int notmain2(int i) {
    return i + 2;
}

main.c

int notmain(int);

int main(int argc, char **argv) {
    return notmain(argc);
}

I use noinline确保所发生的事情不是以下因素的次要影响:notmain是否内联。

编译和反汇编-O1:

gcc -c -flto -O1 notmain.c
gcc -flto -O3 notmain.o main.c
objdump -d a.out

结果:notmain现在和notmain2不存在:

0000000000001040 <main>:
    1040:       f3 0f 1e fa             endbr64
    1044:       e9 f0 00 00 00          jmp    1139 <notmain>
    1049:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

0000000000001139 <notmain>:
    1139:       8d 47 01                lea    0x1(%rdi),%eax
    113c:       c3                      ret

但是,如果我这样做:

gcc -c -flto -O0 notmain.c
gcc -flto -O3 notmain.o main.c
objdump -d a.out

那么两者都存在:

0000000000001040 <main>:
    1040:       f3 0f 1e fa             endbr64
    1044:       e9 f0 00 00 00          jmp    1139 <notmain>
    1049:       0f 1f 80 00 00 00 00    nopl   0x0(%rax)

0000000000001139 <notmain>:
    1139:       f3 0f 1e fa             endbr64
    113d:       55                      push   %rbp
    113e:       48 89 e5                mov    %rsp,%rbp
    1141:       89 7d fc                mov    %edi,-0x4(%rbp)
    1144:       8b 45 fc                mov    -0x4(%rbp),%eax
    1147:       83 c0 01                add    $0x1,%eax
    114a:       5d                      pop    %rbp
    114b:       c3                      ret

000000000000114c <notmain2>:
    114c:       f3 0f 1e fa             endbr64
    1150:       55                      push   %rbp
    1151:       48 89 e5                mov    %rsp,%rbp
    1154:       89 7d fc                mov    %edi,-0x4(%rbp)
    1157:       8b 45 fc                mov    -0x4(%rbp),%eax
    115a:       83 c0 02                add    $0x2,%eax
    115d:       5d                      pop    %rbp
    115e:       c3                      ret

所以我的问题是-O1的变化notmain.o导致优化未完成的目标文件?

有趣的是,我还尝试将其中的确切优化一分为二-O1导致这一点。man gcc列出所有标志-O1启用:

gcc -c -flto -fauto-inc-dec -fbranch-count-reg -fcombine-stack-adjustments -fcompare-elim -fcprop-registers -fdce -fdefer-pop -fdelayed-branch -fdse -fforward-propagate -fguess-branch-probability -fif-conversion -fif-conversion2 -finline-functions-called-once -fipa-modref -fipa-profile -fipa-pure-const -fipa-reference -fipa-reference-addressable -fmerge-constants -fmove-loop-invariants -fmove-loop-stores -fomit-frame-pointer -freorder-blocks -fshrink-wrap -fshrink-wrap-separate -fsplit-wide-types -fssa-backprop -fssa-phiopt -ftree-bit-ccp -ftree-ccp -ftree-ch -ftree-coalesce-vars -ftree-copy-prop -ftree-dce -ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre -ftree-phiprop -ftree-pta -ftree-scev-cprop -ftree-sink -ftree-slsr -ftree-sra -ftree-ter -funit-at-a-time notmain.c
gcc -flto -O3 notmain.o main.c
objdump -d a.out

but notmain2仍然存在。

我厌倦了用以下方式观察 LTO:

lto-dump -dump-body=notmain2 notmain.o

但我没有看到任何明显会产生影响的事情-O1:

Gimple Body of Function: notmain2
int notmain2 (int i)
{
  int _2;

  <bb 2> [local count: 1073741824]:
  _2 = i_1(D) + 2;
  return _2;

}

with -O0:

Gimple Body of Function: notmain2
int notmain2 (int i)
{
  int D.4724;
  int _2;

  <bb 2> :
  _2 = i_1(D) + 2;

  <bb 3> :
<L0>:
  return _2;

}

在 Ubuntu 23.04、GCC 12.2.0 上测试。


如果其他方法都失败,请阅读手册。

请注意,仅在链接时而不是在编译时指定优化级别选项通常是无效的,原因有两个。首先,不进行优化的编译会抑制在链接时收集有效优化所需信息的编译器传递。其次,一些早期的优化过程只能在编译时执行,而不能在链接时执行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么在使用 -O0 编译目标文件时,GCC 不使用 LTO 进行函数死代码消除? 的相关文章

  • ns_initparse 的链接器错误

    这是代码 include
  • 如何使用 #pragma 在 G++ 中启用优化

    我想在没有命令行参数的情况下启用 g 优化 我知道 GCC 可以通过写来做到这一点 pragma GCC optimize 2 在我的代码中 但它似乎在 G 中不起作用 此页面可能有帮助 http gcc gnu org onlinedoc
  • 列出 C 常量/宏

    有没有办法使GNU C 预处理器 cpp 或其他一些工具 列出给定点上的所有可用宏及其值C file 我正在寻找特定于系统的宏 同时移植一个已经精通 UNIX 的程序并加载一堆稀疏的 UNIX 系统文件 只是想知道是否有比寻找定义更简单的方
  • 为什么要在项目中使用#include_next?

    引用iOS有关包装器标头的文档 http developer apple com library ios documentation DeveloperTools gcc 4 0 1 cpp Wrapper Headers html inc
  • gcc 内部使用相同的位表示 int 和 char 吗?

    我只是为了好玩而玩弄 unicode 字符 不使用 wchar t 支持 我只使用常规的 char 数据类型 我注意到 当以十六进制打印它们时 它们显示了完整的 4 个字节 而不是仅一个字节 对于前 考虑这个 c 文件 include
  • GCC 4.7 字符串文字的源字符编码和执行字符编码?

    Linux x86 64 上的 GCC 4 7 是否具有默认字符编码 用于验证和解码 C 源文件中字符串文字的内容 这是可配置的吗 此外 当将字符串数据从字符串文字链接到输出的数据部分时 它是否具有默认的执行字符编码 这是可配置的吗 在任何
  • 如何BSWAP 64位寄存器的低32位?

    我一直在寻找如何将 BSWAP 用于 64 位寄存器的低 32 位子寄存器的答案 例如 0x0123456789abcdef位于 RAX 寄存器内 我想将其更改为0x01234567efcdab89用一条指令 因为性能 所以我尝试了以下内联
  • typeof() 表达式内的副作用

    在 GNUC C 中 您可以使用typeof expression 并且使用内部带有副作用的表达式是合法的 例如 您可以使用以下 C 代码 int x 0 typeof x y 在这种情况下 副作用被忽略 并且 x 之后仍然为零 这是有道理
  • `printf()` 中格式说明符“%qd”的用途是什么?

    我看到格式说明符 qd浏览时github https github com Microsoft clang blob master test Sema format strings c代码 然后我检查了 GCC 编译器 它工作正常 incl
  • 使用 OpenMP 编译会导致内存泄漏

    根据 valgrind 的说法 使用 OpenMP 编译简单的 hello world 程序时可能会导致内存泄漏 这是没有意义的 因为 hello world 程序并没有有意使用任何 OpenMP 功能 假设下面的程序名为hi c并根据 g
  • 分析 ELF 部分和符号大小的工具

    我需要一种方法来分析 ARM 的 GCC 编译器的输出文件 我正在为裸机进行编译 并且我非常关心大小 我可以用arm none eabi objdump由交叉编译器提供 但如果存在用于此任务的工具 则解析输出并不是我渴望做的事情 您知道存在
  • 在 Linux 上将 libquadmath 与 C++ 链接

    我有一个示例代码 include
  • 错误:“std::this_thread”尚未声明

    我尝试使用 std this thread sleep for 函数但收到错误 error std this thread has not been declared 包括标志 GLIBCXX USE NANOSLEEP 还需要什么来强制它
  • 为什么 ld 无法从 /etc/ld.so.conf 中的路径找到库?

    我想添加 opt vertica lib64进入系统库路径 所以我执行以下步骤 1 添加 opt vertica lib64 into etc ld so conf 然后运行ldconfig 2 检查 bash ldconfig p gre
  • 为什么这个未使用的变量没有被优化掉?

    我使用了 Godbolt 的 CompilerExplorer 我想看看某些优化有多好 我的最小工作示例是 include
  • gcc 中 -g 选项的作用是什么

    我看到很多关于 gdb 的教程要求在编译 c 程序时使用 g 选项 我无法理解 g 选项的实际作用 它使编译器将调试信息添加到生成的二进制文件中 此信息允许调试器将代码中的指令与源代码文件和行号相关联 拥有调试符号可以使某些类型的调试 例如
  • gcc 中的“假设”子句

    gcc 最新版本 4 8 4 9 是否有类似于以下的 假设 子句 assume 内置icc支持吗 例如 assume n 8 0 从 gcc 4 8 2 开始 gcc 中没有 assume 的等效项 我不知道为什么 这会非常有用 马夫索建议
  • 如何编译GCC生成的asm?

    我正在玩一些汇编代码 有些事情困扰着我 我编译这个 include
  • 使用 mingw32 在 Windows 上构建 glew 时“DllMainCRTStartup@12”的多个定义

    我关注了这个主题 使用 mingw 使建筑物在 Windows 上闪闪发光 https stackoverflow com questions 6005076 building glew on windows with mingw 6005
  • Ubuntu 11.10 上的 c 数学链接器问题 [重复]

    这个问题在这里已经有答案了 我从 Ubuntu 升级后出现了一些奇怪的错误 10 11 11 04 i dont know 到 11 10 我正在得到一个undefined reference to sqrt 使用 math h 时并与 l

随机推荐