线性 IR 表征程序的一系列操作。是图形 IR 的替代品之一。assembly 语言程序就是某种形式的线性 IR,包含了排好序的指令序列。指令可以包含多个操作,这些操作时并行的。
4.4.1 One-Address Code
略
使用模式:作为 definitive IR,JAVA 使用的 bytecode 基于栈的虚拟机。
4.4.2 Three-Address code
三地址码有吸引力原因
- 紧凑(compact)大多数操作包含 4 个 item,op code,三个名字。opcode 需要一或两个字节,名字典型的使用整数表示。
- 操作数名字的分离可以让编译器自由控制名字和值的重用,三地址码没有析构操作
- 很多现代处理器实现了三地址码操作
抽象层级:三地址码可以包含多种操作以及多种抽象层级。比如可以包含的操作有 jump, branch, load, store,甚至更复杂的操作,比如 max。表征这种复杂操作简化了分析和优化。
使用模式:编译器使用三地址码作为 definitive IR。三地址码的显式名字空间和 load-store memory 模型,非常适合寄存器到寄存器,load-store 机器的优化。
4.4.3 Representing Linear Codes
前端链表是更好的选择,后端比如 instruction scheduler 需要大量重排操作的时候,array 是更好的选择。
4.4.4 Building the CFG from Linear Code
对于 Linear Code 有算法来做
- Finding leaders
- Finding last and adding edges
FindLeaders()
next <- 1
Leader[next++] <- 1
create a CFG node for l[1]
for i <- 2 to n do
if op[i] has a label l[i] then
Leader[next++] <- i
create a CFG node for l[i]
MaxStmt <- next - 1
BuildGraph()
for i <- 1 to MaxStmt do
j <- Leader[i] + 1
while (j <= n and op[j] not belong to Leader) do
j <- j + 1
j <- j - 1
Last[i] <- j
if op[j] is "cbr r[k] -> l[1], l[2]" then
add edge from j to node for l[1]
add edge from j to node for l[2]
else if op[j] is "jumpI -> l[1]" then
add edge from j to node for l[1]
else if op[j] is "jump -> r[1]" then
add edges from j to all labeled statements
end
难题部分 略