The document discusses code generation from a directed acyclic graph (DAG) representation of a basic block. It describes how a DAG makes rearranging the computation order easier than from a linear sequence. It also discusses labeling nodes in a tree representation with the minimum number of registers needed and generating code by evaluating nodes requiring more registers first. Finally, it discusses handling operations like multiplication that require multiple registers in the labeling algorithm.
2. The advantage of generating code for a basic block
from its dag representation is that, from a dag we can
easily see how to rearrange the order of the final
computation sequence than we can starting from a
linear sequence of three-address statements or
quadruples
3. t1 := a + b
t2 := c + d
t3 := e - t2
t4 := t1 - t3
(1) MOV a, R0
(2) ADD b, R0
(3) MOV c, R1
(4) ADD d, R1
(5) MOV R0, t1
(6) MOV e, R0
(7) SUB R1, R0
(8) MOV t1, R1
(9) SUB R0, R1
(10) MOV R1, t4
-
+ -
+a0 b0 e0
c0 d0
t1
t2
t3
t4
4. t2 := c + d
t3 := e - t2
t1 := a + b
t4 := t1 - t3
(1) MOV c, R0
(2) ADD d, R0
(3) MOV e, R1
(4) SUB R0, R1
(5) MOV a, R0
(6) ADD b, R0
(7) SUB R1, R0
(8) MOV R0, t4
-
+ -
+a0 b0 e0
c0 d0
t1
t2
t3
t4
5. The heuristic ordering algorithm attempts to make
the evaluation of a node immediately follow the
evaluation of its leftmost argument.
6. while unlisted interior nodes remain do begin
select an unlisted node n, all of whose
parents have been listed;
list n;
while the leftmost child m of n has no
unlisted
parents and is not a leaf do begin
list m;
n := m;
end
end
8. Label each node of the tree bottom-up with an
integer denoting fewest number of registers
required to evaluate the tree with no stores of
immediate results
Generate code during a tree traversal by first
evaluating the operand requiring more registers
9. if n is a leaf then
if n is the leftmost child of its parent then
label(n) := 1
else
label(n) := 0
else begin
let n1, n2, …, nk be the children of n ordered
by label so that label(n1) label(n2) …
label(nk);
label(n) := max1 i k(label(ni) + i - 1)
end
10. label(n) = max(l1, l2), if l1 l2
l1 + 1, if l1 = l2
t1
t4
t2a b
c
t3
d
e
1
2
1 2
0
1 0
11
For binary interior nodes:
11. Use a stack rstack to allocate registers R0,
R1, …, R(r-1)
The value of a tree is always computed in
the top register on rstack
The function swap(rstack) interchanges the
top two registers on rstack
Use a stack tstack to allocate temporary
memory locations T0, T1, ...
12. op
n1 n2
op
n1 n2
op
n1 n2
label(n1) < label(n2) label(n2) label(n1) both labels r
op
n1 n2n name
name
13. /* case 1 */
begin
let name be the operand represented by n2;
gencode(n1);
print op || name || ',' || top(rstack)
end
/* case 2 */
begin
swap(rstack); gencode(n2);
R := pop(rstack); gencode(n1);
print op || R || ',' || top(rstack);
push(rstack, R); swap(rstack);
end
14. /* case 3 */
begin
gencode(n1);
R := pop(rstack); gencode(n2);
print op || R || ',' || top(rstack);
push(rstack, R);
end
/* case 4 */
begin
gencode(n2); T := pop(tstack);
print 'MOV' || top(rstack) || ',' || T;
gencode(n1); push(tstack, T);
print op || T || ',' || top(rstack);
end
15. gencode(t4) [R1, R0] /* 2 */
gencode(t3) [R0, R1] /* 3 */
gencode(e) [R0, R1] /* 0 */
print MOV e, R1
gencode(t2) [R0] /* 1 */
gencode(c) [R0] /* 0 */
print MOV c, R0
print ADD d, R0
print SUB R0, R1
gencode(t1) [R0] /* 1 */
gencode(a) [R0] /* 0 */
print MOV a, R0
print ADD b, R0
print SUB R1, R0
t1
t4
t2a b
c
t3
d
e
1
2
1 2
0
1 0
11
16. Some operations like multiplication, division,
or a function call normally require more than
one register
The labeling algorithm needs to ensure that
label(n) is always at least the number of
registers required by the operation
label(n) = max(2, l1, l2), if l1 l2
l1 + 1, if l1 = l2
17. +
T1
+
T1
1 l
max(2, l)
l 0
l
+
T1
T4
+
T2 T3
+
Ti3
+
Ti1 Ti2
+
Ti4
+
associative
commutative
largest
commutative
18. Nodes with more than one parent in a dag
are called shared nodes
Optimal code generation for dags on both a
one-register machine or an unlimited number
of registers machine are NP-complete