C 编译器优化(1)

     我打算在这里记录一下C Complier 的一些优化实现策略,本文主要考虑在C Complier 中如何优化到Codesize 最小,并不是打算产生出的代码效率最高,因为目前嵌入式设备的Flash 或着ROM 是“寸土寸金”。因此这样的优化在 CComplier 阶段就显得很重要了。优化我打算写一个系列的工作记录,因此本文之后还会更深入的讲解,这篇主要是讲述  C Complier 如何做这个优化部分,以及优化部分能持续到什么时候,以及如何构建优化的解决方案。

1.  C  Complier 的优化解决思路
 (1)目前 C Complier 的优化从建立语法树,就可以开始优化的动作。
 (2)中间代码的优化工作,这个部分主要是通过DAG图来进行优化。
 (3)代码产生出来之后,可以进行的局部优化(peephole)
 (4)整个工程在编译之后,link 阶段可以进行的多余指令和变量的优化动作
以上的优化部分,都是在可以进行代码调试的基础上进行的,不是将代码优化到VS 或者Gcc那种不能调试的程度,当然那种的难度就会更高。

2 .下面主要讲述在 C Complier 之外的peephole 优化和 link阶段的postlink 优化,然后再进入 C Complier 的内部分别描述各种优化的实施


3.peephole 优化的构建
  peephole 的构建,首先必须熟悉当前要使用的机器指令,同时对机器指令应该能达到写相当精炼的ASM 程序。因为我们的peephole 是基于在ASM 上进行优化。为了能进行局部范围的优化工作,那么应该对指令的各种信息了如指掌。
(1) 指令集信息的收
      一般要收集的信息无非就是四种:
     1) 指令的操作数信息,比如有没有操作数,操作数是工作寄存器(下面使用WR)还是RAM 空间(下面使用M), 如 指令R0 = 0x45;  拿这条指令来说 R0 是一个WR,0x45 是一个立即数 ,那么对待这种类型的汇编指令你就要分析源操作数和目的操作数的信息是什么? MOV AL, 0x45 是和这个指令基本一致,那么我们就应该对这种指令分别记录其源和目的操作数。
    2) 指令的语法信息: 如R0 = 0x45 这是一个简单的赋值语句,那么对待R0 = R0+ R1 + C 这是表示一个操作指令。
    3) 记录指令的类型, 如PUSH 指令,有没有改变FLAG Register 等。
   描述上述信息之后,大家可能就要问,为什么要收集这些信息。因为我们的peephole 是针对这些文本进行处理的,如果我们不将这些信息收集起来,直接处理不但难度很大,而且我的 Complier 就没有人用了,估计我也就失业了。
(2) 如何收集指令的信息
      因为我们都是学过软件工程的,在别人已经有现成的东西可以使用的时候,那么我们就不必要从头开发,同样我们没有必要从头开发。因此我们分析汇编指令可以借助YCC和LEX 自动化分析工具,那么在这里我们使用的是Visual Parser 4.0 以上的版本,网络上可以download 到的。
    写VP的parse 规则这个大家根据自己的指令形式进行写,即可。就是将产生式书写过程。
(3)优化pattern 的收集,那么这个过程是C Complier 产生规则产生出来的代码形成的规定格式,那么只要出现这中格式,就可以进行优化,例如:
PUSH  SSF
R0 = R1 + R0
PUSH SSF
R0 =  SL R0--------------> 表示左移 R0一位后再赋值给R0
那么出现这样的情况其实SSF Register 是不要保存的。
还有PC 上这样的指令
MOV al, temp
MOV temp, al
.........
其中出现没有别的指令修改temp, 和al 的值的话,那么第二句就可以删掉了。当然我这里是一个简单的描述,任何人的 Complier 都应该是不同的。

peephole 的优化原则:

    peephole 的优化原则主要是在局部没有发生跳转和Call 的地方进行的多余指令的删除和替换操作,当然以上除多余指令为主要的目的,替换除非pattern 很稳定的时候,才可以做,负责将会出错 。另外peephole 不能在C 程序中的内嵌汇编上做优化,也不能对user 直接写的ASM 文件中的内容做优化 ,因为用户写的东西不能保证就是制定的pattern ,或者用户就是为了达到某种效果,故意写的指令,这些我们都不得而知。


下一篇  peephole 具体实做。
 主要讲如何分析peephole , 如何将状态机用到 C Complier 的优化之中。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章