Global Optimization
COP-5621, Spring 2024
Table of Contents
Intuition
local optimizations review
homework
live vars intuition won't work
need info from previous blocks
also when you having branches, you've got multiple previous blocks how do we handle this?
if doing dce, what would this mean? what can we conclude? what if the branch is never taken? (why have it in the cfg?) overapproximation soundness, analysis/rewriting -> the same, but not vice-versa (same doesn't necessarily mean analysis and rewriting will happen) sound, analysis says live vars -> actual live vars at runtime complete, live vars at runtime -> analysis says live vars (
live vars
x := inparam y := x outparam := y
live vars, connecting basic blocks
x := inparam y := x if y < 0 then y := y * -1 outparam := y
live vars unioning
x := 2 y := x + 1 # rewrite to y := 3 if inparam > 0 then t := x else t := y outparam := t
reaching definitions which definitions of a variable can reach each point in the program?
if inparam == 0 then x := 1 else x := 2 outparam := x
constant prop
if inparam == 0 then x := 1 y := 2 else x := 2 y := 1 outparam := x + y
reaching defs, undefined var
if inparam == 0 then x := 1 else skip outparam := x
reaching defs, cycle
x := 1 while inparam > 0 then inparam := inparam - x
multiple reaching definitions due to cycle
x := 1 while inparam > 0 then begin inparam := inparam - x; x := 2 end
loop invariants
b := inparam c := 10 while x > 0 do begin a := b + c; y := y + a; x := x - 1 end outparam := y
available expressions common subexpression elimination
a := inparam b := 5 x := a + b y := 10 outparam := a + b
a := inparam b := 5 x := a + b a := 5 outparam := a + b
a := inparam b := 5 x := a + b if inparam > 0 then y := 10 else y := 11 # a + b in both sets outparam := a + b
a := inparam b := 5 x := a + b if inparam > 0 then y := 10 else a := 5 # a + b only in one set outparam := a + b
union makes sense for live vars (any possible path) and reaching definitions (any possible path). but for available expressions, we want all possible paths.
union vs. intersection join states at multiple edges
union means any path intersection means all paths
data flow framework direction initial state values transfer functions (gen and kill) join operator (union or intersection)
fixed-point iteration https://web.stanford.edu/class/archive/cs/cs143/cs143.1128/lectures/15/Slides15.pdf
lattices (union and intersection form a partial-order, always finding hopefully least upper bound https://en.wikipedia.org/wiki/Partially_ordered_set
Review
Straightline code
local, like interpreting the instructions, but collecting sets of states
Branches
combine all possibilities (want to have all possible states)
- notice that this will either be overapproximate (more states/traces than the real program) or underapproximate (fewer states/traces than the real program)
- in the compiler world, we want equivalence, so we overapproximate (and avoid making an optimization unless its equivalent even the overapproximate version)
Conflict data on multiple paths
all paths or some path?
- for our set-based states, any path is union, e.g., live vars we want to know if its live on any path (may be overapproximate, but don't remove dead code unless dead on all paths)
- all paths is intersection, e.g., copy propagation, want to make sure the copy is true on all paths
Cycles
CFG shows them as always infinite
- reach overapproximation in finite number of steps so that analysis will terminate
- dataflow analysis: have a finite set, always enlarge (or shrink) the set
Properties of the the data-flow state
Recall that to handle cycles, we want to overapproximate the state and have a finite number of iterations
Modeling data-flow state
- We can guarantee termination by
- having a finite range of values
- having an operation that combines values in that range
- When combining paths, always increase those values
Total order
- Number line with finite number of states
- Modeling value of x: 0, 1, infinity
- We know which elements are greater than each other
- Simple example: if we see x++ with a cycle, we can keep picking a new element, but we'll eventually hit a single maximum value that never changes (fixpoint)
Partial order
Some states we want for data-flow don't fit in a total order
Example: live vars
- if we see live vars {x, y} and {y, a}, which is greater or less? well neither
- what about {x, y, a} and {x, y} which is greater?
- for live vars, we want to know set inclusion, so greater here is "is superset of"
Partially-ordered set
Just like a number line, but when some elements are neither greater nor less than
This is a nice model for the data we have in data-flow analyses, it has the properties we want
- We have a way to combine elements in a minimal way (least upper bound) - If we make it finite, we can ensure analysis terminates (whether or not program does) - We always combine (join) at multiple in-edges, so we ensure we'll always terminate and overapproximate
Example: live vars
What if {x, y}, {y, a} come in from inedges/cycle?
(Diagram)
Lattice
A partial order with operators to find least upper bound (and/or greatest lower bound)
What makes up a lattice?
- Partial order (values and comparison operator)
- Join (operator for least upper bound, supremum)
- Meet (operator for greatest lower bound, infimum)
- Example lattice: program variables and superset
- Join (union)
- Meet (intersection)
- (Diagram)
Framing data-flow analysis as a lattice
- Values: sets of definitions
- Order operation: superset
- Join: union
- Do we need meet?
- (Diagram)
Putting it all together
- Local analysis state transfer functions
- Combining data from multiple inedges
- States that overapproximate actual runtime state
- Finite and monotonic (can only reach maximum value in finite time)
- Fixpoint: compute states over and over until no more change
- (Diagrams)
Example
slide 88
Program Analysis Discussion
Next time
How to implement the data-flow framework?