通常汇编写的代码具有非常好的速度。但是难懂,所以人们就选择先编译高级语言,然后再修改汇编代码来达到优化目的。但实际上想要写的比编译器好是需要很多的练习的。对于我们这些普通的汇编使用者,就了解点简单的技巧和编译器如何优化的知识就够了。
GNU的编译器一般提供了3个级别的优化。注意优化之前先保存一遍原来的代码。
因为编译器貌似会直接把你的代码改了。。
编译器提供的-o –o2-o3到底做了些什么呢?
虽然可以直接man着看,但是还是自己抄写一遍印象深点。
优化级别1,这个级别包含-f优化功能。
-fdefer-pop | 这个选项是在函数调用的时候值一直保存在堆栈中,然后一次性使用指令把这些值清空。 |
-fmerge-constants | 将相同的常量合并。这个可能很耗时间,但是作用不大。 |
-fthread-jumps | 编译器将经过多个跳转的情况,直接优化从第一个跳转到最后一个目标代码 |
-floop-optimize | 优化程序中的循环,删除在循环内没有改变值的变量赋值操作。减少循环内执行的指令数量。确定如何离开循环的条件分支。 |
-fif-conversion | 通过一些列技巧,减少或删除条件分支。 以减少if-then语句中花费的时间 |
-fif-conversion2 | 结合高级的数学特性,减少实现if-then语句所需的条件分支 |
-fguess-branch | 利用指令周期时间重新安排指令。试图将尽可能多的指令移动到条件分支之前,最充分的利用处理器指令缓存 |
-fguess-branch-probability | 试图确定最可能的条件分支。和延迟分支技术类似。 可能产生不同的汇编代码。 所以很多程序员会选择关闭这个选项。 |
-fcprop-registers | 把寄存器分配给变量,编译器执行第二次检查,减少调度依赖性。删除不必要的寄存器复制操作。 |
优化级别2.这个级别包含优化级别1所有的内容。
-fforce-mem | 在使用变量之前,强制把存放在内存位置中的所有变量都复制到寄存器中. 对于很多指令都涉及到的变量来说,这个优化比较显著. |
-foptimize-sibling-calls | 将递归调用展开乘一系列一般的指令.而不是使用分支. 和指令保持为需要分支操作的单独函数调用相比,这样更快 |
-fstrength-reduce | 对循环执行优化并且删除迭代变量. 迭代变量指的就是类似for循环中类似的i,j的东西. |
-fgcsc | 对生成的所有会变一眼代码执行全局通用子表达式消除例程. 简单来说组合通用代码,消除冗余代码 |
-fcse-follow-jumps | 用来查找那些通过任何途径都不会到达的目标代码. 消除冗余 |
-frerun-cse-after-loop | 先对循环代码优化之后,再次扫描. 确保在展开循环代码之后更进一步地优化循环代码. |
-fdelete-null-pointer-checks | 这个是用来检查空指针的. 编译器假设间接引用空指针将停止程序. 可能意思是增加一种机制让你用了空指针之后就自动关闭程序. |
-fexpensive-optimizations | 执行各种消耗昂贵的优化技术. 但是不一定保证运行时性能能提升. 反而可能一定程度上会产生负面影响. |
-fregmove | 重新分配mov指令中使用的寄存器,并且将其作为其他指令的做操作数,最大化捆绑寄存器使用. |
-fschedule-insns | 重新安排指令,消除等待数据的处理器. 比如在浮点计算的时候, 可以让处理器在等待浮点数运算结果时加载其他指令. |
-fsched-interblock | 跨越指令块调度指令. 非常灵活地移动指令以便等待间期完成的工作最大化. |
-fcaller-saves | 减少寄存器的保存. 对于多个函数一次性调用的时候. |
-fpeephole2 | 允许进行任何计算机特定的观察孔优化 |
-freorder-blocks | 重新安排指令块 以便改进分支操作和代码局部性 |
-fstrict-aliasing | 强制实行高级语言的严格变量规则. 确保不在数据类型之间共享变量. 比如int和float不使用相同的内存区域. |
-funit-at-a-time | 指示编译器在运行优化例程之前读取整个汇编语言代码. 重新安排不消耗大量时间的代码以便优化指令缓存. 但是在编译的时候会消耗相当多的内存 |
-falign-functions | 让函数对准内存中的特定边界的开始位置. 方便分页系统. |
-falign-loops | 让循环尽可能包含在一个对准内存中特定边界的开始. 也就是让循环包含在一个页面之中. |
-fcrossjumping | 对跨越跳转代码的处理. 组合分散在程序各处的相同代码. 可以减少程序长度,但是部一定会对性能产生优化. |
优化级别3.这个整合了前面1 2级优化的全部内容
但是这个级别不能保证将改进最终代码的性能.
-finline-functions | 不为函数创建单独的汇编语言代码 就像内联的优化,把函数代码包含在调用程序的代码中. 或许增加了程序的长度,但是充分利用指令缓存代码 而不是在每次函数调用时进行分支操作,可以提高性能. 我想现在编译器都默认会设置inline标志了,应该用处不大了吧. |
-fweb | 构建保存变量的伪寄存器网络. 伪寄存器包含数据,就像它们是寄存器一样,但是可以使用各种其他优化技术进行优化,比如cse和loop优化技术 |
-fgcse-after-reload | 完全重新加载生成的且优化后的汇编语言代码之后执行第二次gcse优化,帮助消除不同优化代码方式创建的任何冗余段. |
接下来还有一些简单的手动优化的方式,有些太复杂就不看了.
直接展开循环.这个就是将循环直接展开.这个对于变次数的循环可能很难做到吧.
循环检验条件如果是常量,那么先计算之后存放在一个变量中.(这就是通用子表达式消除...书总喜欢说的复杂些..)
我想使用编译器优化就能行了吧.至于其余的更深层次的优化就让汇编高手来做吧!.