Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Register Allocation in Compilers

What is meant by spilling of registers or spill code which appears in Register allocation phase of Code generation where compiler backend must allocate variables to memory or registers?.

like image 636
FancyPants Avatar asked May 28 '15 17:05

FancyPants


People also ask

What is register allocation and assignment?

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.

Why do we need to do register allocation on the output of instructions selection?

Register allocation determines which registers are used to hold the values in the program. In a general-register machine, in which all instructions can operate on all registers, register allocation can be performed strictly after instruction selection.

What is global register allocation?

Register allocation refers to the practice of assigning variables to registers as well as handling transfer of data into and out of registers. Register allocation may occur: On a basic block, known as local register allocation. Over an entire function or procedure, known as global register allocation.

What is Dag register allocation and code selection?

Code generation from DAG is much simpler than the linear sequence of three address code. With the help of DAG one can rearrange sequence of instructions and generate and efficient code. There exist various algorithms which are used for generating code from DAG.


1 Answers

Hardware registers are expensive (both in terms of die area and the number of instruction bits required to address them), and therefore generally quite few in number. Spilling occurs when the number of live variables (or, more accurately, the number of live ranges) at a given program point exceeds the number of available registers.

Consider the following example program executing in an imaginary machine that has two hardware registers. Assume the compiler performs no optimization aside from register allocation.

a := 1   ; liveout: {a}
b := 2   ; liveout: {a,b}
c := 3   ; liveout: {a,b,c}
d := a + b + c

Since a and b are used in the definition of d, their live ranges cross the definition of c. But since the machine only has two registers, it's impossible for a, b and c to all be held in a register when d is defined. At least one of them must be spilled.

In the simplest form of spilling, all definitions of the spilled variable are replaced with stores to a stack slot, and all uses are replaced with loads. Some compilers also have the option of performing register-to-register spilling, meaning that the value is stored to and loaded from a register of a different class. For instance, on x86-64 the compiler could spill a value from a general-purpose register like rax into a SIMD register like xmm0. This has the benefit of reducing memory traffic.

As an alternative to spilling, a compiler may instead perform live range splitting. This involves breaking live ranges into smaller pieces - inserting loads and stores only at the split points - to enable coloring of an otherwise uncolorable interference graph.

As you can probably imagine, the choice of which variable to spill has a significant impact on the performance of the resulting code. Arbitrarily spilling a variable used or defined in a tight loop may have disastrous consequences. As such, a good compiler likely applies some form of heuristics to esimate the cost of spilling each variable before making its choice.

like image 139
Martin Törnwall Avatar answered Sep 23 '22 01:09

Martin Törnwall