Compilers - Lecture 6

February 07, 2021

Lecture 6

Register Allocation Part 2

Live Ranges (live on exit)

Assume i and j are two instructions in a basic block

A value (virtual register) is live between its definition and its uses

  • Find definitions (x <- …) and uses (y <- … x …)
  • From definition to last use its live range
    • How many (static) definitions can you have for a virtual register?
  • Can represent live range as an interval [i,j] (in block)
    • Live on exit

Let MAXLIVE be the maximum, over each instruction i in the block, of the number of values (virtual registers) live at i.

  • If MAXLIVE <= k, allocation should be easy
    • No need to reserve set of F registers for spilling
  • If MAXLIVE > k, some values must be spilled to memory

Finding live ranges is harder in the global case

Example:

  • The live ranges of r1 and r3 do not overlap
    • r2, r3 are live on exit
    • r1 is not live on exit

Physical register ra assigned to r1 can also be re-assigned to r3

Register allocation as a graph coloring problem:

Interference Graph:

  • Nodes: live ranges
  • Edges: live at the same time

Graph coloring problem

  • Color all nodes
  • Use minimal number of colors such that no adjacent nodes have the same color

Answer: 2 colors

Top Down Allocator

The idea:

  • Machine has k physical registers
  • Keep the “busiest” values in an assigned register
  • Use the feasible (reserved) set, F, for the rest
  • F is the minimal set of registers needed to execute any instruction with all operands in memory
    • Move values with no assigned register from/to memory by adding LOADs and STOREs (SPILL CODE)

Basic algorithm (not graph coloring!)

  • Rank values by number of occurrences (or some other metric)
  • Allocate first k to F values to registers
  • Rewrite code (with spill code) to reflect these choices

Example

Take the following ILOC code with the live ranges (on exit) for each virtual register

loadI   1028    => r1 // r1
load    r1      => r2 // r1 r2
mult    r1,r2   => r3 // r1 r2 r3
loadI   5       => r4 // r1 r2 r3 r4
sub     r4,r2   => r5 // r1    r3    r5
loadI   8       => r6 // r1    r3    r5 r6
mult    r5,r6   => r7 // r1    r3          r7
sub     r7,r3   => r8 // r1                   r8
store   r8      => r1 //