范例:
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);
}
型
我使用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
型
但是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;
}
型
使用-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上测试。
1条答案
按热度按时间vyswwuz21#
如果所有这些都失败了,请阅读手册。
请注意,仅在链接时而不是在编译时指定优化级别选项通常是无效的,原因有二。首先,不进行优化的编译会抑制在链接时收集有效优化所需信息的编译器遍数。第二,一些早期的优化过程只能在编译时执行,而不能在链接时执行。