0% found this document useful (0 votes)
15 views57 pages

13 Static Analysis Classic Problems

Uploaded by

scribd.boil024
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views57 pages

13 Static Analysis Classic Problems

Uploaded by

scribd.boil024
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 57

Compiler

Static Analysis:
Classic Problems
© Copyright 2005, Matthew B. Dwyer and Robby. The syllabus and lectures for this course are copyrighted
materials and may not be used in other course settings outside University of Nebraska-Lincoln and Kansas
State University in their current form or modified form without express written permission of one of the
copyright holders. During this course, students are prohibited from selling notes to or being paid for taking
notes by any person or commercial firm without the express written permission of one of the copyright holders.
Classic Static Analysis Problems

 We’ll look at four analyses


 Reaching Definitions (RD)
 Available Expressions (AE)
 Very Busy Expressions (VBE)
 Live Variables (LV)
 We’ll see what’s similar and different and
generalize to data flow frameworks

Compiler Static Analysis: Classic Problems 2


Reaching Definition (RD)
Analysis
 RD analysis determines
 For each program point, which assignments
may have been made and not overwritten
along some path to that program point.

Compiler Static Analysis: Classic Problems 3


RD Example
static int factorial(int n) {
int result;
int i;
[StaticJavaLib.assertTrue(n >= 1);]1
[result = 1;]2
[i = 2;]3
[while (i <= n) {
[result = result * i;]5
[i = i + 1;]6
}]4
[return result;]7
}

For example, the definition in 2 may reach 5,


we describe this more compactly by saying
(result, 2) reaches the entry 5.
Compiler Static Analysis: Classic Problems 4
Denoting RD
 We can describe the set of reaching definitions
for the entry and exit of each program point as:
 RD : Lab* → P(Var* \times D)
entry
 RD : Lab → P(Var \times D)
exit * *
 Notes
 Lab and Var* are the subsets of labels and variables
*
occurring in the program under analysis, e.g., { 1, 2,
…, 7 } and { n, result, i }
 D = { •, ? } \cup Lab
*
 dot (•) denotes definition from a formal parameter (or
a field)
 question mark (?) denotes unknown definition
Compiler Static Analysis: Classic Problems 5
RD Flow Equations
 A definition is killed in a block if its variable
is defined in the block

killRD : Lab* → P(Var* \times D)

 killRD([x = e ;]l) = { (x, d’) | d’ \in D }


 killRD([…]l) = \emptyset

Compiler Static Analysis: Classic Problems 6


RD Flow Equations
 A definition is generated in a block if the
block assigns a value to a variable

genRD : Lab* → P(Var* \times D)

 genRD([x = e ;]l) = { (x, d) }


 genRD([…]l) = \emptyset

Compiler Static Analysis: Classic Problems 7


Kill and Gen sets?
static int factorial(int n) {
int result;
int i;
[StaticJavaLib.assertTrue(n >= 1);]1
[result = 1;]2
[i = 2;]3
[while (i <= n) {
[result = result * i;]5
[i = i + 1;]6
}]4
[return result;]7
}

Compiler Static Analysis: Classic Problems 8


Gen/Kill RD Example
l killRD(l) genRD(l)
1 \emptyset \emptyset
2 { (r, ?), (r, 2), (r, 5) } { (r,2) }
3 { (i,?), (i, 3), (i, 6) } { (i,3) }
4 \emptyset \emptyset
5 { (r, ?), (r, 2), (r, 5) } { (r,5) }
6 { (i,?), (i, 3), (i, 6) } { (i,6) }
7 \emptyset \emptyset

Compiler Static Analysis: Classic Problems 9


RD Flow Equations
 The flow equations are now expressed
using the two functions
{ (x,•) | x \in (Param* \cup Field*)} \cup
RDentry(l ) = { (x,?) | x \in Local* }, if l = binit
 { RDexit(l’ ) | l’ \in preds (l ) }, otherwise

RDexit(l ) = (RDentry(l ) \ killRD(l )) \cup genRD(l )

Compiler Static Analysis: Classic Problems 10


RD Flow Equations
 Data flow propagated along control flow
 Information at entries is calculated in terms of
information at preceding exits
 Information at program entry, i.e., binit,
represents the fact that local variables are
undefined when the program starts.
 In a language like Java where all fields (and
parameters) are guaranteed to have initial
values one would use dot (•)

Compiler Static Analysis: Classic Problems 11


Entry and Exit sets?
static int factorial(int n) {
int result;
int i;
[StaticJavaLib.assertTrue(n >= 1);]1
[result = 1;]2
[i = 2;]3
[while (i <= n) {
[result = result * i;]5
[i = i + 1;]6
}]4
[return result;]7
}

Compiler Static Analysis: Classic Problems 12


RD Example
l RDentry(l) RDexit(l)
1 { (n,•),(r,?),(i,?) } { (n,•),(r,?),(i,?) }
2 { (n,•),(r,?),(i,?) } { (n,•),(r,2),(i,?) }
3 { (n,•),(r,2),(i,?) } { (n,•),(r,2),(i,3) }
4 { (n,•),(r,2),(r,5),(i,3),(i,6) } { (n,•),(r,2),(r,5),(i,3),(i,6) }
5 { (n,•),(r,2),(r,5),(i,3),(i,6) } { (n,•),(r,5),(i,3),(i,6) }
6 { (n,•),(r,5),(i,3),(i,6) } { (n,•),(r,5),(i,6) }
7 { (n,•),(r,2),(r,5),(i,3),(i,6) } { (n,•),(r,2),(r,5),(i,3),(i,6) }

Compiler Static Analysis: Classic Problems 13


Observation
RD
Direction forward
Solution least
binit (f) / blast { (x,•) | x \in
(Param* \cup
(b) Value Field*)} [ { (x,?) | x
\in Local* }

Combining \cup
Operator
Description may
Paths some

Compiler Static Analysis: Classic Problems 14


Bounds
 A subset Y of a poset (S, \sqsubseteq) has l \in S as
an
 upper bound if \forall l’ \in Y. l’ \sqsubseteq l
 e.g., ( { 1, 2, 3 }, ≤ ), Y = { 2 }, l \sqsubseteq { 2, 3 }
 lower bound if \forall l’ \in Y. l \sqsubseteq l’
 e.g., ( { {1}, {2}, {1, 2} }, \subseteq), Y = { {1, 2} }, l \in { {1}, {2}, {1,
2} }
 A least upper bound (lub) l of Y is an upper bound such
that l \sqsubseteq l’ where l’ is an upper bound of Y and
exists k such that l’ \sqsubseteq k (least)
 e.g., ( { 1, 2, 3 }, ≤ ), Y = { 2 }, lub = 2
 A greatest lower bound (glb) l of Y is a lower bound such
that l’ \sqsubseteq l where l’ is a lower bound of Y and
exists k such that k \sqsubseteq l’
 e.g., ( { {1}, {2}, {1, 2} }, \subseteq), Y = { {1}, {2} }, no glb unless
you consider \emptyset as sitting on the bottom of the lattice
Compiler Static Analysis: Reaching Definition (RD) Analysis 15
Finding Bounds
 If they exist, lub and glb are unique.
 The least upper bound of two subsets is denoted
l1 \sqcup l2 which is called the join operator.
 e.g., ( { 1, 2, 3, 4 }, ≤ ), {2, 3} \sqcup {2} = 3
 The greatest lower bound of two subsets is
denoted l1 \sqcap l2 which is called the meet
operator.
 e.g., ( { {}, {1}, { 2 }, {1, 2} }, \subseteq), { {1} } \
sqcap { {1, 2} } = {1}
Compiler Static Analysis: Reaching Definition (RD) Analysis 16
Observation
RD
Direction forward
Solution least
binit (f) / blast { (x,•) | x \in
(Param* \cup
(b) Value Field*)} \cup
{ (x,?) | x \in
Local* }

Combining \cup
Operator
Description may
Paths some

Compiler Static Analysis: Classic Problems 17


Available Expressions (AE)
Analysis
 AE analysis determines
 For each program point, which expressions
must have already been computed, and not
later modified, on all paths to the program
point.

Compiler Static Analysis: Classic Problems 18


AE Example
int x;
int y;
[x = a + b;]1
[y = a * b;]2
[while (y > a + b) {
[a = a + 1;]4
[x = a + b;]5
}]3

a + b has already been computed whenever


statement 3 is reached so we don’t have to
recompute it
Compiler Static Analysis: Classic Problems 19
Denoting AE
 We can describe the set of available
expressions for the entry and exit of each
program point as a set of expression
drawn from the non-trivial syntactic
expression in the program AExp*:
 AE : Lab* → P(AExp*)
entry
 AE : Lab* → P(AExp*)
exit
 The non-trivial expressions for our
program are: a + b, a * b, and a + 1
Compiler Static Analysis: Classic Problems 20
AE Flow Equations
 A expression is killed in a block if any of its
variables is defined in the block

killAE : Lab* → P(AExp*)

 killAE([x = e ;]l) = { a’ \in AExp* | x \in vars(a’)}


 killAE([…]l) = ;

Compiler Static Analysis: Classic Problems 21


AE Flow Equations
 An expression is generated in a block if it is evaluated in
the block and none of the variables in the expression are
subsequently defined in the block

genAE : Lab* → P(AExp*)

 genAE([x = e ;]l) = {a’ \in AExp(e) | x \not\in vars(a’ ) }


 genAE([while (b) … ]l) = AExp(b)
 genAE([if (b) … ]l) = AExp(b)
 genAE([… ]l) = ;

Compiler Static Analysis: Classic Problems 22


Kill and Gen sets?
int x;
int y;
[x = a + b;]1
[y = a * b;]2
[while (y > a + b) {
[a = a + 1;]4
[x = a + b;]5
}]3

Compiler Static Analysis: Classic Problems 23


Gen/Kill AE Example
l killAE(l) genAE(l)
1 \emptyset { a + b }
2 \emptyset { a * b }
3 \emptyset { a + b }
4 {a + b, a * b, a + 1} \emptyset
5 \emptyset { a + b }

Compiler Static Analysis: Classic Problems 24


AE Flow Equations
 The flow equations are now expressed
using the two functions
\emptyset, if l = binit
AEentry(l ) =
 { AEexit(l’ ) | l’ \in preds (l ) }, otherwise

AEexit(l ) = (AEentry(l ) \ killAE(l )) \cup genAE(l )

Compiler Static Analysis: Classic Problems 25


AE Flow Equations
 Data flow propagated along control flow
 Information at entries is calculated in
terms of information at preceding exits
 Information at program entry, i.e., b ,
init
indicates that no expressions have been
computed at that point

Compiler Static Analysis: Classic Problems 26


Entry and Exit Sets?
int x;
int y;
[x = a + b;]1
[y = a * b;]2
[while (y > a + b) {
[a = a + 1;]4
[x = a + b;]5
}]3

Compiler Static Analysis: Classic Problems 27


AE Example
l AEentry(l) AEexit(l)
1 \emptyset { a + b }
2 { a + b } { a + b, a * b }
3 { a + b } { a + b }
4 { a + b } \emptyset
5 \emptyset { a + b }

Compiler Static Analysis: Classic Problems 28


Observation
RD AE
Direction forward forward
Solution least greatest
binit (f) / blast { (x,•) | x \in \emptyset
(Param* \cup
(b) Value Field*)} \cup
{ (x,?) | x \in
Local* }

Combining \cup \cap


Operator
Description may must
Paths some all

Compiler Static Analysis: Classic Problems 29


Very Busy Expressions (VBE)
Analysis
 VBE analysis determines
 For each program point, which expressions
must be used before any variable occurring in
them is redefined along all paths leading from
the exit of the program point.

Compiler Static Analysis: Classic Problems 30


VBE Example
int x;
int y;
[if (a > b) {
[x = b - a;]2
[y = a - b;]3
} else {
[y = b - a;]4
[x = a - b;]5
}]1

a - b and b - a have subsequent uses on all paths


leading from the conditional and are therefore very
busy. We can hoist their calculation out of the
conditional bodies.
Compiler Static Analysis: Classic Problems 31
Denoting VBE
 We can describe the set of very busy
expressions for the entry and exit of each
program point as a set of expression
drawn from the non-trivial syntactic
expression in the program AExp*:
 VBE : Lab* → P(AExp*)
entry
 VBE : Lab* → P(AExp*)
exit
 The non-trivial expressions for our
program are: a - b and b - a
Compiler Static Analysis: Classic Problems 32
VBE Flow Equations
 A expression is killed in a block if any of its
variables is defined in the block

killVBE : Lab* → P(AExp*)

 killVBE([x = e ;]l) = { a’ \in AExp* | x \in vars(a’)}


 killVBE([…]l) = ;

Compiler Static Analysis: Classic Problems 33


VBE Flow Equations
 An expression is generated in a block if it is evaluated in
the block

genVBE : Lab* → P(AExp*)

 genVBE([x = e ;]l) = AExp(e)


 genVBE([while (b) … ]l) = AExp(b)
 genVBE([if (b) … ]l) = AExp(b)
 genVBE([… ]l) = \emptyset

Compiler Static Analysis: Classic Problems 34


Kill and Gen sets?
int x;
int y;
[if (a > b) {
[x = b - a;]2
[y = a - b;]3
} else {
[y = b - a;]4
[x = a - b;]5
}]1

Compiler Static Analysis: Classic Problems 35


Gen/Kill VBE Example
l killVBE(l) genVBE(l)
1 \emptyset \emptyset
2 \emptyset { b – a }
3 \emptyset { a - b }
4 \emptyset { b – a }
5 \emptyset { a - b }

Compiler Static Analysis: Classic Problems 36


VBE Flow Equations
 The flow equations are now expressed
using the two functions
\emptyset, if l = blast
VBEexit(l ) =
 { VBEentry(l’ ) | l’ \in succs (l ) }, otherwise

VBEentry(l ) = (VBEexit(l ) \ killVBE(l )) \cup genVBE(l )

Compiler Static Analysis: Classic Problems 37


VBE Flow Equations
 Data flow information is propagated opposite to
execution order
 Information at exits is calculated in terms of
information at succeeding entries
 Statement entry information is calculated from
exit information
 Information at program entry, i.e., blast,
represents the fact that there are no uses of
expressions after termination

Compiler Static Analysis: Classic Problems 38


Entry and Exit Sets?
int x;
int y;
[if (a > b) {
[x = b - a;]2
[y = a - b;]3
} else {
[y = b - a;]4
[x = a - b;]5
}]1

Compiler Static Analysis: Classic Problems 39


VBE Example
l VBEentry(l) VBEexit(l)
1 { a – b, b - a } { a – b, b - a }
2 { a – b, b - a } { a – b }
3 { a - b } \emptyset
4 { a – b, b - a } { a – b }
5 { a – b } \emptyset

Compiler Static Analysis: Classic Problems 40


Observation
RD AE VBE
Direction forward forward backward
Solution least greatest greatest
binit (f) / blast { (x,•) | x \in \emptyset \emptyset
(Param* \cup
(b) Value Field*)} \cup
{ (x,?) | x \in
Local* }

Combining \cup \cap \cap


Operator
Description may must must
Paths some all all

Compiler Static Analysis: Classic Problems 41


Live Variable (LV) Analysis
 LV analysis determines
 For each program point, which variables must
have a subsequent use on some path from
the program point prior to the next definition of
that variable.

Compiler Static Analysis: Classic Problems 42


LV Example
int x;
int y;
int z;
[x = 2;]1
[y = 4;]2
[x = 1;]3
[if (y > x) {
[z = y;]5
} else {
[z = y * y;]6
}]4
[x = z;]7

Since the value assigned at 1 is never used,


the assignment can be removed

Compiler Static Analysis: Classic Problems 43


Denoting LV
 We can describe the set of live variables
for the entry and exit of each program
point as a subset of variables in the
program Var*:
 LVentry : Lab* → P(Var*)
 LVexit : Lab* → P(Var*)

Compiler Static Analysis: Classic Problems 44


LV Flow Equations
 A variable is killed in a block if it is defined
in the block

killLV : Lab* → P(Var*)

 killLV([x = e ;]l) = { x }
 killLV([…]l) = \emptyset

Compiler Static Analysis: Classic Problems 45


LV Flow Equations
 A variable (use) is generated in a block if it is evaluated
in the block

genLV : Lab* → P(Var*)

 genLV([x = e ;]l) = vars(e)


 genLV([while (b) … ]l) = vars(b)
 genLV([if (b) … ]l) = vars(b)
 genLV([… ]l) = \emptyset

Compiler Static Analysis: Classic Problems 46


Kill and Gen Sets?
int x;
int y;
int z;
[x = 2;]1
[y = 4;]2
[x = 1;]3
[if (y > x) {
[z = y;]5
} else {
[z = y * y;]6
}]4
[x = z;]7

Compiler Static Analysis: Classic Problems 47


Gen/Kill LV Example
l killLV(l) genLV(l)
1 {x} \emptyset
2 {y} \emptyset
3 {x} \emptyset
4 \emptyset { x, y }
5 {z} {y}
6 {z} {y}
7 {x} {z}

Compiler Static Analysis: Classic Problems 48


A word on Maximal Blocks

c = a+b; kill = {c,d}


d = c-a; use = {a,b}
jmp y

Compiler Static Analysis: Reaching Definition (RD) Analysis 49


A word on Maximal Blocks

d = c-a; kill = {c,d}


c = a+b; use = {a,b,c}
jmp y

Compiler Static Analysis: Reaching Definition (RD) Analysis 50


Method calls?
 kill and gen sets for method calls?
 All the save-on-call registers are killed
 All the registers in the parameter build are
used
 If two parameters passed via registers,
then those registers are generated

Compiler Static Analysis: Classic Problems 51


Method returns?
 kill and gen sets for method returns?
 We have discussed the SYNC node, what
should be in that node (BTW, the RET
instruction can be the SYNC node)
 Only R12! Assume everyone obeys the stack
convention so save-on-entry is only used
when saved and restored
 No need to clutter graph with save-on-entry
 Handled automatically
Compiler Static Analysis: Classic Problems 52
LV Flow Equations
 The flow equations are now expressed
using the two functions
\emptyset, if l = blast
LVexit(l ) =
 { LVentry(l’ ) | l’ \in succs (l ) }, otherwise

LVentry(l ) = (LVexit(l ) \ killLV(l )) \cup genLV(l )

Compiler Static Analysis: Classic Problems 53


LV Flow Equations
 Data flow opposite to control flow
 Information flows in at the final node since we
are interested in future uses of variables
 For whole programs, there are no uses
subsequent to a final node so we use \
emptyset as the exit value of final statements
 If we are analyzing a part of a program we would
take Var* as the initial value since there might be
subsequent uses.

Compiler Static Analysis: Classic Problems 54


Entry and Exist Sets?
int x;
int y; 1
int z;
[x = 2;]1
[y = 4;]2
[x = 1;]3 2
[if (y > x) {
[z = y;]5
} else { 3
[z = y * y;]6
}]4
[x = z;]7
T 4 F
5 6

Compiler Static Analysis: Classic Problems 55


LV Example
l LVentry(l) LVexit(l)
1 \emptyset \emptyset
2 \emptyset {y}
3 {y} { x, y }
4 { x, y } {y}
5 {y} {z}
6 {y} {z}
7 {z} \emptyset

Compiler Static Analysis: Classic Problems 56


Observation
RD AE VBE LV
Direction forward forward backward backward
Solution least greatest greatest least
binit (f) / blast { (x,•) | x \in \emptyset \emptyset \emptyset
(Param* \cup
(b) Value Field*)} \cup
{ (x,?) | x \in
Local* }

Combining \cup \cap \cap \cup


Operator
Description may must must may
Paths some all all some

Compiler Static Analysis: Classic Problems 57

You might also like