Since IR can use as many temporaries as possible, we need to rewrite the code to use no more temporaries than machine registers
Temporaries t_1, t_2 can share the same register if at any point in the program, at most one of t_1, t_2 can be live. (cannot share if both live at same time)
Register Interference Graph (RIG): variables in conflict in at least one place are connected.
If a RIG is k-colorable (NP-Hard), then it is possible to only use k registers to run the code.
Spilling: If a RIG is not k-colorable, we need to store (spill) temporaries in the memory.
We do:
fa
f
, insert f := load fa
f
, insert store f, fa
But which temporary should we spill? Some heuristics:
spill temporaries with most conflict (resolve more conflicts)
spill temporaries with few definitions and uses (small overhead)
avoid spilling in inner loops (speed)
RISC: machine with general registers
CISC: machine who's registers have limited instructions avaliable
Many people believe compiler now manage cache better than programmer can.
A common optimization is matrix tiling, which we have discussed in 15-213. However, most compiler don't implement loop tiling, so programmers have to do this most of the time.
Table of Content