deep

a Cross Development Platform for Java

User Tools

Site Tools


dev:crosscompiler:backend_ppc:register_allocation

This is an old revision of the document!


Register Allocation

Starting with the SSA form for each result of an SSA instruction a register has to be assigned. However, it must be decided how the registers of a processor will be used generally.

Register Usage

Registers can be classified as dedicated, volatile or nonvolatile. Dedicated are register with a special purpose, such as the stackpointer. Volatile means, that this register might be used any time. It does not have to be stored when another method is called. Nonvolatile registers must be saved in the prologue of a method before they can be used and after use they must be restored. The number of volatile and nonvolatile registers must be equal for all methods.

Register State Use
R0 volatile method prologue, scratch register
R1 dedicated stack pointer
R2 volatile 1. parameter, return value
R3 volatile 2. parameter, return value (if long, lower 4 bytes of long)
R4-R10 volatile further parameters
R11-R12 volatile local variables, working registers
R13-R31 nonvolatile local variables, working registers
F0 volatile working register
F1 volatile 1. parameter, return value
F2-F8 volatile further parameters
F9-F12 volatile local variables, working registers
F13-F19 nonvolatile local variables, working registers
F20-F22 volatile utility register for compiler specific subroutines
F23-F31 nonvolatile local variables, working registers

Local variables are assigned volatile registers. However, if the live range of an SSA value incorporates a method call, a nonvolatile register has to be used. These will be assigned in decreasing order from R31/F31. As working registers volatile registers are used. If there are not enough of them, nonvolatiles (just below the locals) are assigned.
Optimization: If a method is a leaf method, it would not be necessary to copy the parameters from their volatile registers into nonvolatile registers.
For the translation of certain SSA instructions (e.g. of type long) further auxiliary registers are needed. They are assigned and reserved by the register allocator as well. If FPR's are needed for auxiliary registers, they are not reserved but F20..F22 will be used. They are exclusively used in compiler specific subroutines and never need saving.

Parameter Passing

Parameters are passes in R2..R10 and F1..F8.
In the interface cgPPC/Registers you can find the definitions about which registers are used for volatiles and nonvolatiles and which are used for parameter passing. Important: the number of parameter registers must be smaller or equal than the number of volatiles.

Determination of Live Range

We determine for the results of all SSA instructions up to which instruction they are used (field end). Results of phi-functions must be handled separately. Such results might be used as operands of instructions which are placed further upstream. For this reason the live range of a phi-function does not start with its instruction but with its first use of an operand or the phi-function itself. Hence, phi-function need a field start.

Determine Used Parameters

Parameters are passed in volatile registers. Some of them have to be copied to nonvolatile registers. Some parameters might not be used at all in a method. This can be determined in the exit set of the last node. If a value is null in that set the parameter with this index was never loaded and hence no register must be reserved. The following example demonstrates parameter usage.

  float m2(long a, float b, double c, byte[] d, short e, int f, int g) {
    a = 0x7545 & a;
    e += 100;
    T08Calls.classMethod(d[2]);
    e = (short)(20 + e);
    g |= 0x223344;
    c = 3.2;
    int h = g - e;
    T08Calls.classMethod(h);
    short i = (short)h;		
    return b;
  }
Variablethisabcdefg
TyprefLongFloatDoubleByteArrayShortIntegerInteger
Register Typ volnonVolvolvolvol nonVol
not usedx x
Register R3,R4FR31FR2R5R6 R31

Register Assignment

Finally the results of all SSA instructions will be assigned a register.

Releasing of Registers of phi-Functions

As described above, phi-functions have a field last which is used to make sure that a registers of a phi-function lives to the very end of its loop. At the this end the register of the phi-function (which is actually given in its join value) could be released. However, at this stage we already passed the phi-function. For this purpose all phi-functions are referenced in a linked list (with the field next) in the first SSA instruction of the node following the node with the phi-function.

Loading of Parameters

All sCloadLocal instructions use the same register as their parameter. In case of join != null, the referenced phi function gets the same register.

Reservation of Auxiliary Registers

Some instruction need 1 or 2 additional (auxiliary) registers. These will be reserved and stored in regAux1 and regAux2. At the end of the instruction they can be released again. It's possible that the result of the SSA instruction occupies the same register as one of the auxiliary registers.

Releasing of Operand Registers

Registers of operands, whose live range expires, must be released. If they are of type Long, this step must happen at the very end.

Reservation of a Result Register

The register pool will be searched for a free register for the result. The result type determines if 1 or 2 GPR's or a FPR must be reserved. The following two cases must be considered.

1. join != null

The same register must be assigned as the result of the phi function. If not handled yet the phi function has to be dealt with first. It can happen that several phi funtions occupy the same index in the state array:

  switch(i) {
  case 0: return 0;
  case 1: i++; break;
  case 2: return 2;
  case 3: i += 3;
  case 4: i += 4; break;
  default: return -1;
  ..
  return i + 3;

In those cases all phi functions with the same index get the same register assigned.

2. Loading of a Constant

If a constant can be used as immediate operand by the machine instruction no register has to be reserved. However, if the value shows up in the state array (index >= 0), it must be loaded into a register anyway. This is the case with the conditional operator. A register must be assigned also in case of join != null.

Releasing of Result Registers

The result register can be released immediately if the live range already expires.

dev/crosscompiler/backend_ppc/register_allocation.1515076920.txt.gz · Last modified: 2018/01/04 15:42 by ursgraf