compiler construction in4020 – lecture 7
Post on 14-Jan-2016
55 Views
Preview:
DESCRIPTION
TRANSCRIPT
Compiler constructionin4020 – lecture 7
Koen Langendoen
Delft University of TechnologyThe Netherlands
• attribute grammars • formal attributes per symbol: inherited & synthesized
• attribute evaluation rule per production
• dependency graphs
• evaluation order
Summary of lecture 6
S -attributed grammarsL -attributed grammarsmulti-visit grammars
Quiz
3.1 Which of the following items belong to a non-terminal, and which to a production?
(a) inherited attribute(b) synthesized attribute(c) attribute evaluation rule(d) dependency graph(e) visiting routine
Overview
• context handling
• annotating the AST• attribute grammars
• manual methods
• symbolic interpretation
• data-flow equations
program text
lexical analysis
syntax analysis
context handling
annotated AST
tokens
AST
Manual methods for analyzing the AST
• preparing the grounds for code generation• constant propagation
• last-def analysis (reaching definitions)
• live analysis
• common subexpression elimination
• dead-code elimination
• ...
• we need flow-of-control information
Threading the AST
• determine the control flow graph that records the successor(s) of AST nodes
-
*
‘c’
‘4’
*
‘a’
‘b’
*
‘b’
first
last• intermediate code
PUSH b
PUSH b
MUL
PUSH 4
PUSH a
MUL
PUSH c
MUL
SUB
Threading the AST
• result is a post-order traversal of the AST
• global variable: Last node pointer
PROCEDURE Thread binary expression (Expr node pointer):
Thread expression (Expr node pointer .left operand);
Thread expression (Expr node pointer .right operand);
// link this node to the dynamically last node
SET Last node pointer .successor TO Expr node pointer;
// make this node the new dynamically last node
SET Last node pointer TO Expr node pointer;
*
‘c’
‘4’
*
‘a’
Multiple successors
• problem: threading is built around single Last node pointer
IF
condition THEN ELSE
first
last
Multiple successors
• problem: threading is built around single Last node pointer
• solution: introduce join node
IF
condition THEN ELSE
first
last
FI
Symbolic interpretation
• behaviour of code is determined by (the values of) variables
• simulate run-time execution at compile time
• attach a stack representation to each arrow in the control flow graph
• an entry summarizes all compile-time knowledge about the variable/constant
Symbolic interpretation
condition
IF
THEN ELSE
FI
Symbolic interpretation
condition
IF
THEN ELSE
>
y 0yx
5
yx
5
5
yx
5
50
yx
5
T
yx
5
yx
5
yx
5
x = 7;
yx
57
yx
5
dead
code
FI
merge
Exercise (5 min.)
• draw the control flow graph for
while C do S od
• propagate initial stack
when C represents y>x
and S stands for x:=7
yx
5
Answers
Answers
condition
WHILE
BODY
yx
5
yx
5
yx
5yx
5
b
yx
57
Simple symbolic interpretation
• used in narrow compiler
• simple properties + simple control-flow
• example: detecting the use of uninitialized variables
• maintain property list
• advance list through
control flow graph
int foo(int n)
{ int first;
while (n-- > 0) {
if (glob[n] == KEY)
first = n;
}
return first;
}
Trackinguninitialized variables
• parameter declaration:
• variable declaration:
• expression:
• assignment:
• control statement
• fork nodes:
• join nodes:
add (ID:Initialized) tuple
add (ID:Uninitialized) tuple
check status of used variables
set tuple to (ID:Initialized)
copy list
merge lists
merge( Init, Init) = Init
merge( Uninit, Uninit) = Uninit
merge( x, x) = Maybe
int foo(int n)
{ int first;
while (n-- > 0) {
if (glob[n] == KEY)
first = n;
}
return first;
}
Simple symbolic interpretation
• flow-of-control structures with one entry and one exit point (no GOTOs)
• the values of the property are severely constrained (see book)
• example: constant propagation
Constant propagation
• record the exact value iso Initializedint i = 0;
while (condition) {
if (i>0) printf("loop reentered\n");
…
i++;
}
• simple symbolic interpretation fails
// i == 0
// i == 0
// i == 1
// i == {0,1}
Full symbolic interpretation
• maintain a property list for each entry point (label), initially set to empty
• traverse flow of control graphL: merge current-list into list-L
continue with list-L
jump L;merge current-list into list-L
continue with the empty list
• repeat until nothing changedguarantee termination – select suitable property
int i = 0;
while (condition) {
if (i>0) printf("loop reentered\n");
…
i++;
}
int i = 0;
L:
if (condition) {
if (i>0) printf("loop reentered\n");
…
i++;
goto L;
}
Constant propagation
• full symbolic interpretation
• property: unknown < value < any
// i == 0
// i == 1// empty
// i == ANY
// i == ANY
// i == 0
// i == 0// i == ANY
// i == ANY
Break
Data flow equations
• “automated” full symbolic interpretation• stack replaced by collection of sets
• IN(N)• OUT(N)
• semantics are expressed by constant sets• KILL(N)• GEN(N)
• equations• IN(N) = M predecessor[N] OUT(M)
• OUT(N) = IN(N) \ KILL(N) GEN(N)
n = n-1;
IN
OUT
Data flow equations
• solved through iteration (closure algorithm)• data-flow nodes may not change the stack
• individual statements• basic blocks
• example: trackinguninitialized variables• properties: I x, M x, U x• GEN(x = expr ;) =• KILL(x = expr ;) =
int foo(int n)
{ int first;
while (n-- > 0) {
if (glob[n] == KEY)
first = n;
}
return first;
}{I x}{U x, M x}
int foo(int n)
{ int first;
L: n = n-1;
if (n >= 0) {
if (glob[n] == KEY)
first = n;
goto L;
}
return first;
}
T
T
Data flow equations
• solved through iteration (closure algorithm)• data-flow nodes may not change the stack
• individual statements• basic blocks
• example: trackinguninitialized variables• properties: I x, M x, U x• GEN(x = expr ;) =• KILL(x = expr ;) =
{I x}{U x, M x}
if (glob[n] == KEY)
first = n;
goto L;
return first;
L: n = n-1;
if (n >= 0)
F
F
1
2
3
4
5
6
{}
{}
{}
{}
{}
{}
IN(N) = M predecessor[N] OUT(M)
OUT(N) = IN(N) \ KILL(N) GEN(N)
Iterative solution
• initialization: set all sets to empty
• iterate from top to bottom
{I n, U f}
{I n, U f}
{I n, U f}
{I n, U f}
{I n, I f}
{I n, M f}
{I n, M f}
{I n, M f}
T
T F
return first;6
F
first = n;4
goto L;5
L: n = n-1;1
int foo(int n)
{ int first;0
if (glob[n] == KEY)3
if (n >= 0)2
statement KILL GEN
0 In Uf
1 Un Mn In
4 Uf Mf If
Iterative solution
statement
iteration 1 iteration 2
KILL GEN IN OUT IN OUT
0 In Uf In Uf In Uf
1 Un Mn In In Uf In Uf In Uf In Uf
2 In Uf In Uf In Mf In Mf
3 In Uf In Uf In Mf In Mf
4 Uf Mf If In Uf In If In Mf In If
5 In Mf In Mf In Mf In Mf
6 In Uf In Uf In Mf In Mf
Efficient data-flow equations
• limit to (set of) on/off properties• set union = bitwise OR• set difference = bitwise AND NOT
• combine statements into basic blocks• KILL[S1;S2] = KILL[S1] KILL[S2]
• GEN[S1;S2] = GEN[S2] (GEN[S1] \ KILL[S2])
• sort data-flow graph• depth-first traversal (break cycles!)
Live analysis
• a variable is live at node N if the value it holds is used on some path further down the control-flow graph; otherwise it is dead
• useful information for register allocation
• information must flow “backwards” (up) through the control-flow graph• difficult for symbolic interpretation• easy for data flow equations
Solving data-flow equations
• forwards
• backwards
IN(N) = M predecessor[N] OUT(M)
OUT(N) = IN(N) \ KILL(N) GEN(N)
if (cond)
IN
OUT
OUT(N) = M successor[N] IN(M)
IN(N) = OUT(N) \ KILL(N) GEN(N)
Exercise (5 min.)
• determine the KILL and GEN sets for the property “V is live here” for the following statements
statement S KILL GEN
v = a b
v = M[i]
M[i] = v
f(a1, ... ,an)
v = f(a1, ... ,an)
if a>b then goto L1 else goto L2
L:
goto L
Answers
• determine the KILL and GEN sets for the property “V is live here” for the following statements
statement S KILL GEN
v = a b
v = M[i]
M[i] = v
f(a1, ... ,an)
v = f(a1, ... ,an)
if a>b then goto L1 else goto L2
L:
goto L
{v} {a,b} \ KILLS[S]
{v} {i} \ KILLS[S]
{} {i,v}
{} {a1, ... ,an}
{v} {a1, ... ,an} \ KILLS[S]{} {a,b}
{} {}
{} {}
Exercise (7 min.)
• draw the control-flow graph for the following code fragment
• perform backwards live analysis using the KILL and GEN sets from the previous exercise
double average(int n, double v[])
{ int i;
double sum = 0.0;
for (i=0; i<n; i++) {
sum += v[i];
}
return sum/n;
}
Answers
OUT(N) = M successor[N] IN(M)
IN(N) = OUT(N) \ KILL(N) GEN(N)
statement KILL GEN
1
2
3
4
2
3
1
4
Answers
OUT(N) = M successor[N] IN(M)
IN(N) = OUT(N) \ KILL(N) GEN(N)
statement KILL GEN
1
2
3
4
sum = 0.0;
i = 0;
if (i<n)
sum += v[i];
i++;
return sum/n;
2
3
1
4
Answers
sum = 0.0;
i = 0;
if (i<n)
sum += v[i];
i++;
return sum/n;
live: n
live: n, i, sum
live: n, i, sum
live: n, sum
live: n, i, sum
OUT(N) = M successor[N] IN(M)
IN(N) = OUT(N) \ KILL(N) GEN(N)
statement KILL GEN
1 sum, i
2 i, n
3 sum, i sum, i
4 sum, n
2
3
1
4
Answers
statement
iteration 1 iteration 2 iteration 3
KILL GEN OUT IN OUT IN OUT IN
0 n
1 sum, i i, n n i, n, sum n
2 i, n i, n i, n, sum i, n, sum i, n, sum i, n, sum
3 sum, i sum, i i, n i, n, sum i, n, sum i, n, sum i, n, sum i, n, sum
4 sum, n n, sum i, n, sum i, n, sum
process nodes top to bottom (from 0 to 4)
processing nodes in reverse (from 4 to 0) requires only two iterations
Summary
manual methods for annotating the AST• threading
• symbolic interpretation
• data-flow equations
symbolic interpretationdata-flow equations
simple full
method stack-based simulation IN, OUT, GEN, KILL sets
granularity AST node basic block
algorithm one-pass iterative iterative
direction forwards forwards & backwards
Homework
• study sections:• 3.2.4 interprocedural data-flow analysis
• 3.2.5.1 live analysis by symbolic interpretation
• assignment 1:• replace yacc with LLgen
• deadline April 9 08:59
• print handout for next week [blackboard]
top related