TODO: 用while写法的程序会不会循环展开?
一个简单的累加求和程序:
1 | TYPE S=0; |
很多人都觉得这个程序写得不好,编译器不能生成很好的汇编代码。于是有了以下的几种“优化”:
1 |
|
上面的几种版本都合理,但是这些优化都是建立在编译器不能生成高效的汇编代码的假设上的。
下面来看下编译器生成的结果(vs2010,release):
1 | for(int i = 0;i < SIZE; i++) { |
可见编译器生成的代码是最好的代码,消灭了中间变量i,减少了循环次数,消灭了会造成CPU不能乱序执行的因素。
BTW:
有人可能会有疑问:要是size不是偶数,编译器能生成类似的高效汇编代码不?
当SIZE = 9999时:
1 | //当SIZE = 9999时,编译器把中间结果放到三个寄存器中,perfect |
当SIZE = 9997 时:
1 | //当SIZE = 9997时,有点复杂,先把a[0]到a[9995]累加到ecx和edx中 |
上面的分析都是SIZE,即数组的大小是已知情况下,那个数组大小是未知情况下,编译器又会怎样?
1 | TYPE mySum(TYPE* a, int size){ |
生成的汇编代码:
1 | //先累加a[0] 到 a[size-2] |
总结
C++的编译器生成的汇编代码在绝大多数情况下都和人写出的最好的汇编代码相当。
关键的一点是编译器会不断升级,适应新的cpu指令,体系等,手写的汇编代码则通常悲剧了。
知道编译器能优化到什么程度,编译器到底怎样优化,是程序员很重要的素质。