Open In App

Register Allocations in Code Generation

Registers are the fastest locations in the memory hierarchy. But unfortunately, this resource is limited. It comes under the most constrained resources of the target processor. Register allocation is an NP-complete problem. However, this problem can be reduced to graph coloring to achieve allocation and assignment. Therefore a good register allocator computes an effective approximate solution to a hard problem. 
 



Figure – Input-Output 

The register allocator determines which values will reside in the register and which register will hold each of those values. It takes as its input a program with an arbitrary number of registers and produces a program with a finite register set that can fit into the target machine. (See image) 



Allocation vs Assignment: 

Allocation – 
Maps an unlimited namespace onto that register set of the target machine. 

Allocation ensures that code will fit the target machine’s reg. set at each instruction. 

Assignment – 
Maps an allocated name set to the physical register set of the target machine.  

General register allocation is an NP-complete problem:  

Local Register Allocation And Assignment: 
Allocation just inside a basic block is called Local Reg. Allocation. Two approaches for local reg. allocation: Top-down approach and bottom-up approach. 

Top-Down Approach is a simple approach based on ‘Frequency Count’. Identify the values which should be kept in registers and which should be kept in memory. 

Algorithm: 

  1. Compute a priority for each virtual register.
  2. Sort the registers into priority order.
  3. Assign registers in priority order.
  4. Rewrite the code.

Moving beyond single Blocks:  

Following is a way to find out Live ranges in a block. A live range is represented as an interval [i,j], where i is the definition and j is the last use. 

Global Register Allocation and Assignment: 
1. The main issue of a register allocator is minimizing the impact of spill code; 

2. Global allocation can’t guarantee an optimal solution for the execution time of spill code. 
3. Prime differences between Local and Global Allocation: 

4. To make the decision about allocation and assignments, the global allocator mostly uses graph coloring by building an interference graph. 
5. Register allocator then attempts to construct a k-coloring for that graph where ‘k’ is the no. of physical registers. 

6. Global Allocator uses several approaches, however, we’ll see top-down and bottom-up allocations strategies. Subproblems associated with the above approaches.  

Discovering Global Live Ranges: 
How to discover Live range for a variable? 

Figure – Discovering live ranges in a single block 

The above diagram explains everything properly. Let’s take the example of Rarp, it’s been initialized at program point 1 and its last usage is at program point 11. Therefore, the Live Range of Rarp i.e. Larp is [1,11]. Similarly, others follow up.  

Figure – Discovering Live Ranges 

Estimating Global Spill Cost: 

Interference and Interference Graph: 

Figure – Building Interference Graph from Live Ranges 
 

From the above diagram, it can be observed that the live range LRA starts in the first basic block and ends in the last basic block. Therefore it will share an edge with every other live Range i.e. Lrb, Lrc,Lrd. However, Lrb, Lrc, Lrd doesn’t overlap with any other live range except Lra so they are only sharing an edge with Lra. 

Building an Allocator: 

Top-Down Colouring

  1. Tries to color live range in an order determined by some ranking functions i.e. priority based.
  2. If no color is available for a live range, the allocator invokes either spilling or splitting to handle uncolored ones.
  3. Live ranges having k or more neighbors are called constrained nodes and are difficult to handle.
  4. The unconstrained nodes are comparatively easy to handle.
  5. Handling Spills: When no color is found for some live ranges, spilling is needed to be done, but this may not be a final/ultimate solution of course.
  6. Live Range Splitting: For uncolored ones, split the live range into sub-ranges, those may have fewer interferences than the original one so that some of them can be colored at least.

Chaitin’s Idea: 

Coalescing copies to reduce degree: 
The compiler can use the interference graph to coalesce two live ranges. So by coalescing, what type of benefits can you get? 

Figure – Coalescing Live Ranges 

Comparing Top-Down and Bottom-Up allocator: 

Figure – Coalescing Live Ranges
 


Article Tags :