Wk 8/9, Ch 10/11 – Liveness
Analysis and Register Allocation
|
|
|
|
|
|
|
|
Time to put the infinite numbers of
temporaries into real registers |
|
Using control flow graphs |
|
Calculating liveness using dataflow
analysis |
|
The temporaries are the data |
|
Produces an interference graph indicating
which temporaries are simultaneously live |
|
Register allocation |
|
By colouring the interference graph
with K colours |
|
K colours == K registers in the machine |
Liveness
|
|
|
|
A temporary (register) is live |
|
when its value may be used in the
future |
|
Two temporaries can use the same
register if they are not live simultaneously |
Step 1: Control Flow Graph
|
|
|
|
In a CFG |
|
the statements of the program are nodes |
|
if s2 may follow s1, draw an edge
between them |
|
|
Finding Live Ranges
|
|
|
Temporary t is live on all incoming
edges to a node n where t is used |
|
Temporary t is dead on all incoming
edges to a node n where t is defined |
|
Live Ranges are consecutive sequences
of edges where a temporary is live |
|
When live ranges overlap, multiple
registers must be used |
Finding Live Ranges : a
dataflow analysis
|
|
|
|
Liveness of the temporaries flows
around the edges of the CFG |
|
Terminology |
|
Pred[ n ], Succ[ n ] – direct
predecessor, successor nodes of n |
|
Use[ n ], Def[ n ] – temporaries used
or defined at node n |
|
Variable is live-in if it is live on
any incoming edge to a node. Live-out
similarly. |
|
|
Dataflow equations
|
|
|
|
in[ n ] = use[ n ] u (out[ n ] – def[ n
] ) |
|
in[n] is the set of temporaries that
are live-in at node n |
|
out[ n ] = Union of the live-in
temporaries to all nodes in succ[ n ] |
|
out[n] is the set of temporaries that
are live-out at node n |
|
|
|
Equations solved using an iterative
approach to filling the sets in[n] and out[n] |
|
Repeatedy treat equations as assignment
statements until no change to in[n] and out[n] across an iteration |
Static vs. Dynamic liveness
|
|
|
|
Some programs will never take certain
branches dynamically (at execution) |
|
Allows us to define dynamic liveness |
|
However predicting branching behaviour
requires complex analysis |
|
In fact the Halting Problem can be used
to show that full behaviour can never be predicted, in general |
|
We stick to static liveness, based on
CFGs |
|
Assuming execution can always follow
all branches |
Determining Interference
|
|
|
|
Attempt to allocate t1…tm temporaries
into r1…rn machine registers |
|
Any condition preventing ti and tj from
being allocated to rk is an interference |
|
Commonly overlapping live ranges |
|
Also, when ti is generated by an
instruction that cannot address rk |
|
Draw an interference graph |
|
Where nodes are the temporaries of the
program |
|
Edges represent interference between 2
temporaries |
Register Allocation
|
|
|
|
by colouring the interference graph |
|
No nodes in interference graph joined
by an edge may have the same colour |
|
Aim for K-colouring with K m/c
registers |
|
If there is no K-colouring for the
graph, we may have to spill some values into memory |
|
NP-complete problem – but we have a
linear time approximation with four phases |
|
Build, Simplify, Spill, Select |
|
|
Simplify
|
|
|
|
Pick a node with fewer than K
neighbours |
|
Remove it and its edges from the graph |
|
And place onto a stack of removed nodes |
|
If the remaining graph can be
K-coloured, then so can the complete graph |
|
Recursively remove another node… |
|
|
Select
|
|
|
|
Ignore Spill just now, assume we
removed all nodes to the stack |
|
Rebuild graph by popping stack one
element at a time |
|
Give the element a colour |
|
There will always be an available
colour, since the node had less than K neighbours |
|
|
Spill
|
|
|
|
Suppose on simplify that all nodes have
significant degree (degree <= K) |
|
Pick and mark a node for spilling |
|
Decision is to represent it in memory
during execution |
|
Optimistically assume spilled node can
be allocated with neighbours |
|
Stack it, then continue with the
simplify |
Select after having to Spill
|
|
|
|
|
|
When the spill node was stacked, it was
unclear whether it would be colourable |
|
During select |
|
May find that the K or more neighbours
of the spill node already use all K colours |
|
In which case, this is an actual spill |
|
Don’t colour, continue with Select to
find other actual spills |
|
Otherwise, the node can be coloured |
If Select cannot colour a
node…
|
|
|
|
|
Rewrite program to |
|
Fetch value from memory just before use |
|
Store value back just after each
definition |
|
Creates several new temporaries with
tiny live ranges |
|
Since these will interfere with other
temporaries, the algorithm is repeated |
|
One or two iterations is usually enough |
Coalescing
|
|
|
|
Any source and destination nodes of a
move can be coalesced if they don’t interfere |
|
Although beware joining two nodes that
make a K-colourable graph subsequently uncolourable |
|
Safe strategies exist |
|
E.g. coalesce x and y if new node has
fewer than K neighbours of significant degree |
|
More complex sequence of operations
when register allocating with coalescing |
Finally,
|
|
|
Some nodes precoloured to represent
specific m/c registers – e.g. SP
(P246) |
|
Extra excitement with caller-save and
callee-save registers (P247-) |
|
Extensive implementation details given
in remainder of Chapter 11 for Graph Col |
|
A few remaining pieces to glue it all
together and we’re done |