for循环次数不同,编译器生成的代码就不同,为何?
我用VC10写了几行小程序,编译release版
- C/C++ code
int main(void){ int i=0; for(int c=0;c<11;++c){//循环11次,因为10次以下循环本身会被优化掉。 i+=c; } printf("%d\n",i); return 0;}
发现for循环反汇编代码是这样的:
- C/C++ code
for(int c=0;c<11;++c){0040101E cmp eax,0Bh 00401021 jge main+25h (401025h) i+=c;00401023 mov esi,eax 00401025 add ecx,edx 00401027 add ecx,esi }
然后我修改一下循环的次数从11改成12,发现生成的反汇编代码变复杂了:
- C/C++ code
for(int c=0;c<12;++c){00401004 xor eax,eax 00401006 xor esi,esi 00401008 xor edx,edx 0040100A xor ecx,ecx 0040100C lea esp,[esp] i+=c;00401010 add edi,eax 00401012 lea ecx,[ecx+eax+1] 00401016 lea edx,[edx+eax+2] 0040101A lea esi,[esi+eax+3] 0040101E add eax,4 00401021 cmp eax,0Ch 00401024 jl main+10h (401010h) }
现在i+=c这条语句的代码怎么变得这么复杂? 这是什么样的优化技术么?
我发现c=16的时候,代码和c=12是一样的。
并且,c=13的时候,代码和c=11是一样的。
而c=15的时候,生成的代码又是另一种:
- C/C++ code
for(int c=0;c<15;++c){00401003 xor eax,eax 00401005 xor edx,edx 00401007 xor ecx,ecx 00401009 lea esp,[esp] i+=c;00401010 add esi,eax 00401012 lea ecx,[ecx+eax+1] 00401016 lea edx,[edx+eax+2] 0040101A add eax,3 0040101D cmp eax,0Fh 00401020 jl main+10h (401010h) }
这到底是怎么一回事? 我猜想是编译器的某种优化技术,但是不知道具体是什么技术。
各位高人能解释一下么?
[解决办法]
循环变量使用CPU寄存器优化
[解决办法]
膜拜赵老师
[解决办法]
定值循环,编译器优化的空间很大,icc甚至能直接给你扩展成无循环……
你用变量循环(变量必须从外部读入),生成的才是真正的循环
[解决办法]
估计是考虑速度的优化。12和16可以被4整除,所以4次循环放到了一次里面,15可以被3整除,11和13是质数。
应该和编译时的参数有关。