目标语言
-
代码生成器的任务
- 指令选择
- 寄存器分配和指派
- 指令排序
-
地址
-
静态分配
-
call callee
ST callee.staticArea, #here + 20 BR callee.codeArea
-
return
BR *callee.staticArea
-
name
LD 112, #0 LD 12(SP), #0
-
-
栈式分配
-
call callee
ADD SP, SP, #caller.recordSize ST 0(SP), #here + 16 BR callee.codeArea
-
return
BR *0(SP) SUB SP, SP, #caller.recordSize
-
-
基本块与流图
- 确定 leader
- 第一个三地址指令
- 任一个跳转指令
- 任一个跳转目标指令
- 活跃性
- 开始时非临时变量活跃
- 反向扫描
- i: x = y + z
- x: 不活跃(之前的值不使用),无后续使用
- y,z: 活跃,指明下一次使用设置为语句 i
- 循环定义
- 存在唯一入口结点,前驱在循环之外,到达其余结点路径必然经过该结点
DAG
- DAG 图构造
- 为基本块中每个出现的变量建立结点
- x = y op z:建立指令结点 N,标号 op,令 x 和 N 关联
- x = y:假设 y 关联 N,则 x 关联 N
- 消除死代码:在 DAG 图上消除没有附加活跃变量的根节点
- 数组引用
- x=a[i] 对应于 =[] 的结点
- a[j]=y 对应于 []= 的结点
- 指针赋值、过程调用:无法消除死码
- 重组基本块:如果两个指令间互相影响,则其顺序不该改变
代码生成器
- 尽可能把值保留在寄存器中
- 寄存器描述符:寄存器存放了哪些变量
- 地址描述符:各个变量的当前值存放在哪些位置
- getReg(I): 根据寄存器描述符合地址描述符等数据流信息,为指令 I 选择最佳的寄存器
- 减少 LD/ST 指令
寄存器分配
- v 的地址描述符可以在别的地方找到
- v 就是计算结果变量
- v 在之后不会被使用
- 生成保存指令 ST v, R 并修改地址描述符
优化
- 窥孔优化:使用滑动窗口检查目标指令
- 冗余指令消除
- 控制流优化
- 代数化简/强度消减
- 机器特有指令使用
- 全局寄存器分配
- 树重写实现指令选择
- 重写规则:replacement <- template { action }