Intermediate code uses “unlimited” temporaries. We have more temporaries than there are registers. Key: assign multiple temporaries to each register example Consider: a := c + d e := a + b f := e - 1 notice how a and e are both dead after use, we can then allocate: r1 := r2 + r3 r1 := r1 + r4 r1 := r1 - r1 key: *you can share a register between t_{1} and t_{2} if at any point at most one of t_1 and t_2 are alive. algorithm liveness check go through liveness analysis to see what’s live or not at any particular moment. register inference graph construct an undirected graph where: a node for each temporary an edge between t_1, t_2 if they are live at the same time two temporaries can’t be at the same register if there’s an edge between them. Think of this as a clique problem for every group of live variables from the step above. coloring Notice that the graph above is k colorable iff all variables can fit in k registers as no two adjacent nodes will share the same color as they occur simultaneously. This is naively an NP hard problem. And a coloring also may not exist. observation pick a node t with fewer than k neighbors in the RIG eliminate t and its edges from RIG if the result is k colorable, then so is the original graph since t has fewer than k neighbors, and then coloring it will just allow us to use the remaining color for t algorithm to k_color: remove a node with less than k neighbors; stick it on a stack repeat step 1 until graph is empty while stack is not empty pop assign a color; since at every state here the thing we popped has less than k, we can find a distinct color under k we have a failure case when we are unable to peel the graph until empty in step 2. if so, peel as much as you can, and then… pick a node (following some heuristics, see below) remove it and stick it somewhere else keep going to previous algorithm’s step 2 when we put the node you evicted back in, there’s a chance that you can still color it. if a variable is not colorable, we stick it into the stack. We now make a control flow graph where we load the variable and write to the variable. This allows us to recompute liveness since the liveness is reduced to right before load and uses. also each “live” of f is independent, and so we will have more nodes on the graph, etc. who do we spill? if we have a case where everybody’s edges is above k-1, who do we spill? general goals: “reduce number of loads” spill with the most conflicts spill with few definition and uses avoid spilling in inner loops

[[curator]]
I'm the Curator. I can help you navigate, organize, and curate this wiki. What would you like to do?