C语言 gcc如何优化从1到100求和到5050



我用gcc -O3 -S a.c编译了以下c程序:

#include <stdio.h>
int main() {
int sum = 0;
for (int i = 0; i <= 100; i++) {
sum += i;
}
printf("%d", sum);
}

生成的汇编代码如下:

.section    __TEXT,__text,regular,pure_instructions
.build_version macos, 10, 15    sdk_version 10, 15, 4
.globl  _main                   ## -- Begin function main
.p2align    4, 0x90
_main:                                  ## @main
.cfi_startproc
## %bb.0:
pushq   %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq    %rsp, %rbp
.cfi_def_cfa_register %rbp
leaq    L_.str(%rip), %rdi
movl    $5050, %esi             ## imm = 0x13BA
xorl    %eax, %eax
callq   _printf
xorl    %eax, %eax
popq    %rbp
retq
.cfi_endproc
## -- End function
.section    __TEXT,__cstring,cstring_literals
L_.str:                                 ## @.str
.asciz  "%d"
.subsections_via_symbols

就好像GCC运行了代码,注意到循环时间已经确定,并且GCC替换了整个计算结果为5050.

movl $5050, %esi

gcc是如何做这种优化的?这种优化的学名是什么?

我试图找到特定的标志,但没有运气。我只能用-O1复制你的结果,所以我在那之后所做的是手动添加-O1启用的所有标志。但是当我这样做的时候,我无法复制结果。

在文档

中可以读到

不是所有的优化都是由一个标志直接控制的。本节只列出带有标志的优化。

所以我认为这是由-O1添加的没有标记的东西完成的。

这是我尝试的:

$ gcc -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-profile  
-fipa-pure-const  -fipa-reference  -fipa-reference-addressable 
-fmerge-constants  -fmove-loop-invariants  -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 -S k.c 
cc1: warning: this target machine does not have delayed branches
$ grep "5050" k.s
$ gcc -O1 -S k.c
$ grep "5050" k.s
movl    $5050, %esi
$ 

参考https://gcc.gnu.org/onlinedocs/gcc-4.5.2/gcc/Optimize-Options.html,循环展开(-funroll-loops)和RTL上的正向传播传递(-fforward-propagate)被启用,优化级别为-O,-O2,-O3,-Os

可以试着添加-funroll-loops-fforward-propagate来确认吗?