You are on page 1of 27

Compiler

Design
Spring 2017

8.6 Live variables


Dr. Zoltán Majó

Compiler Group – Java HotSpot Virtual Machine


Oracle Corporation
Live variables

§ Foundations for several optimizations


§ If a variable is not live, it’s dead.
§ No need to store value in dead variables
§ Outline
§ Data flow problem
§ Transfer function
§ Examples

2
Wishlist

§ Given a statement S
§ dest = operand1 ⊕ operand2
§ Compiler would like to know at point P if there is a further
use of dest
§ I.e., there is a statement S’ that uses dest and there is a path from P
to Pbefore_S’
§ One interesting point is Pafter_S or Pafter_B (with B the basic
block of S)
§ But every point could be interesting
§ Like to know if some operandi is used again in another statement

3
Data flow problem
§ Similar to “reaching definitions” but not interested what has
happened prior to reaching P but what happens after P
§ Consider all paths that start at P and go to EXIT
§ A variable V is live at point P if there is a path from P to EXIT that
contains a statement S that uses V, and there is no definition of V
on this path between P and S.
§ Path can start anywhere
§ Often we care about paths that start after a definition of V
§ A single path with a use is enough for V to be live at P
§ A variable that is not live is called dead
§ Recall that we assume all statements have clearly identifiable
operands and destinations

4
Live variables

§ Live variable analysis determines for all points P the set of


variables that are live
§ We care primarily about live variables at the end of a basic
block.
§ Handling a basic block is easy if we know what’s live at the end
§ There are many optimizations that are based on live variable
analysis
§ If a variable is dead at P then it’s not necessary to store the variable
§ If a register is needed and one of the registers contains a dead
variable, this register can be used right away – no need to save the
current content

5
S1: V = … B
S2: W = expr
S3: = X ⊕ V
S4: = Y ⊕ 1
§ No need to store value S5: = Z
computed by S2 in
variable W
Live = {X , Z}
§ If expr has no side effect
stmt can be removed
§ V is local to basic block B
§ If Y is in a register this
register can be released
after S4

6
Transfer function
… B
d: … = var ⊕ …

§ var is live at the start of basic block B if there is no stmt in B


prior to d that defines var

7
Transfer function
… B
d: … = var ⊕ …
d”: var = …

§ var is live at the start of basic block B if there is no stmt in B


prior to d that defines var

8
Transfer function
d’: var = B
d: … = var ⊕ …

§ var is not live at the start of basic block B as there is a stmt in


B prior to d that defines var
§ Definition d’

9
Transfer function
… B
d: … = var ⊕ …

§ Define for basic block B


§ defB = { var | var is defined in B prior to any use of var in B }
§ useB = { var | var is used in B prior to any definition of var in B }
§ Definitions and uses of a variable: must be conservative
§ In def only if we are sure the variable is set
§ In use if there is a chance that the value is used

10
12
ENTRY
Running example
d1: i = m – 1
def = {i, j, a}
d2: j = n
use = {m, n } d3: a = …

def = {}
d4: i = i + 1
use = {i, j} d5: j = j - 1

def = {a}
use = ∅ d6: a = …

def = {i}
use = ∅ d7: i = …

From Aho et al “Compilers”, p 604 EXIT


13
Transfer function

§ Notice we may be interested in the set of live variables at


the start of a basic block
§ So far: local analysis
§ def and use determine effect of statements for basic block in isolation
§ Global information determined by statements in basic block
and statements in subsequent basic blocks
§ Eventually we also figure out what’s live at the end of a basic block

§ Set of live variables at the end of a basic block


§ Determined by statements in subsequent basic blocks
§ Another term: live == downward exposed

14
Transfer function

§ How do we extend transfer function to consider subsequent


basic blocks?

15
IN(B) = {v1, v2, …, vn}
Transfer function

d: …= var ⊕ …

§ For a basic block B we define OUT(B) = {v’1, v’2, …, v’m}


§ IN(B) = { var | var live at Pbefore_B }
§ OUT(B) = { var | var live at Pafter_B }

§ Variable v ∈IN(B)
§ v is used in B prior to any definition, i.e. v ∈ useB
§ v ∈ OUT(B) and v not set by statements in B, i.e. v ∉ defB
§ IN(B) = useB ∪ (OUT(B) – defB)
16
Transfer function
B2
… …
B3

B1
...

§ Given IN(B1)
§ What should be OUT(B2) and OUT(B3)?
§ OUT(B2) = IN(B1), OUT(B3) = IN(B1)

17
18
Transfer function
... B1

B2 … B3 …

§ Given IN(B2) and IN(B3)


§ What should be OUT(B1)?
§ A variable var is live at a point P if there is a path from P to EXIT such that
var is used along that path prior to any definition
§ Must consider all paths starting at P

19
20
Transfer function
... B1

B2 … B3 …

§ Given IN(Bi)
§ OUT(B) = ∪ Bi, Bi is successor of B in CFG IN(Bi)

21
Finding IN and OUT

§ defB and useB capture what happens inside a basic block

22
ENTRY
Running example
d1: i = m – 1
def = {i, j, a}
d2: j = n
use = {m, n } d3: a = …

def = {}
d4: i = i + 1
use = {i, j} d5: j = j - 1

def = {a}
use = ∅ d6: a = …

def = {i}
use = ∅ d7: i = …

From Aho et al “Compilers”, p 604 EXIT


23
Finding IN(B) and OUT(B)

§ N basic blocks, 2×N sets IN / OUT


§ System with 2×N unknowns
§ Solve by iterating until a fixed point is found

§ How to start iteration?


§ Safe assumption IN[EXIT] = ∅
§ Nothing is live at the end

24
Finding live variables

IN[EXIT] = ∅

Initialize IN[B] = ∅ for ∀ B ≠ EXIT

while (changes to any IN(B)) {


for (each basic block B ≠ EXIT) {
OUT(B) = ∪ Bi, Bi is successor of B in CFG IN(Bi)
IN(B) = useB ∪ (OUT(B) – defB)
}
}

25
Finding live variables

IN[EXIT] = ∅

Initialize IN[B] = ∅ for ∀ B ≠ EXIT

while (changes to any IN(B)) {


for (each basic block B ≠ EXIT) {
OUT(B) = ∪ Bi, Bi is successor of B in CFG IN(Bi)
IN(B) = useB ∪ (OUT(B) – defB)
}
}

26
Initialize IN[B] = ∅
while (changes to any IN(B)) {
for (each basic block B ≠ EXIT) { ENTRY
OUT(B) = ∪ Bi, Bi is successor of B in CFG IN(Bi)
IN(B) = useB ∪ (OUT(B) – defB)
} d1: i = m – 1 IN(B1) =

def = {i, j, a}
d2: j = n
use = { m, n } d3: a = … OUT(B1) =

d4: i = i + 1 IN(B2) =
def = {}
use = {i, j} d5: j = j - 1 OUT(B2) =

IN(B3) =
d6: a = …
def = {a} OUT(B3) =
use = ∅
IN(B4) =
def = {i} d7: i = …
use = ∅ OUT(B4) =

From Aho et al “Compilers”, p 604


EXIT IN(EXIT)
29
Incomplete example – to be continued.
zmajo 30

You might also like