This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
dev:crosscompiler:backend:register_allocator [2018/01/04 15:30] – created ursgraf | dev:crosscompiler:backend:register_allocator [2019/08/29 16:53] (current) – [Determine Used Parameters] ursgraf | ||
---|---|---|---|
Line 4: | Line 4: | ||
===== Register Usage ===== | ===== Register Usage ===== | ||
Registers can be classified as // | Registers can be classified as // | ||
- | | 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: | ||
- | 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 // | ||
+ | * [[dev: | ||
+ | * [[dev: | ||
===== Resolving of Phi-Functions ===== | ===== Resolving of Phi-Functions ===== | ||
The operands of a phi-function must all get the same register as the result of the phi-function. For this purpose all these operands have a field //join//. \\ | The operands of a phi-function must all get the same register as the result of the phi-function. For this purpose all these operands have a field //join//. \\ | ||
Line 60: | Line 39: | ||
===== Determine Used Parameters ===== | ===== 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. | + | 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 on a PPC platform. |
<code java> | <code java> | ||
float m2(long a, float b, double c, byte[] d, short e, int f, int g) { | float m2(long a, float b, double c, byte[] d, short e, int f, int g) { | ||
Line 92: | Line 71: | ||
Some instruction need 1 or 2 additional (auxiliary) registers. These will be reserved and stored in //regAux1// and // | Some instruction need 1 or 2 additional (auxiliary) registers. These will be reserved and stored in //regAux1// and // | ||
==== Releasing of Operand 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. | + | 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 ==== | ==== 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. | 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. | ||
Line 113: | Line 92: | ||
==== Releasing of Result Registers ==== | ==== Releasing of Result Registers ==== | ||
The result register can be released immediately if the live range already expires. | The result register can be released immediately if the live range already expires. | ||
+ | |||
+ | ===== Locals on the Stack ===== | ||
+ | Local variables which cannot be assigned a register get assigned a stack slot. Stack slots are numbered from 0x100. The code generator will handle the transfer to and from these stack slots. Whenever the code generator tries to translate an SSA instruction and one of the operands is on the stack, the following has to be dones: | ||
+ | |||
+ | * load stack slot into free register | ||
+ | * execute instruction | ||
+ | |||
+ | If the result of the SSA instruction is assigned a stack slot, the code generator will have to save to the stack: | ||
+ | |||
+ | * execute instruction, | ||
+ | * store destination register onto stack | ||
+ | |||
+ | During register allocation of a method a variable // | ||
+ |