2016-12-02 21:09:20 +01:00
# Register Allocation (x64 Backend)
`HostLoc` s contain values. A `HostLoc` ("host value location") is either a host CPU register or a host spill location.
2018-02-05 23:30:39 +01:00
Values once set cannot be changed. Values can however be moved by the register allocator between `HostLoc` s. This is
handled by the register allocator itself and code that uses the register allocator need not and should not move values
between registers.
2016-12-02 21:09:20 +01:00
The register allocator is based on three concepts: `Use` , `Def` and `Scratch` .
* `Use` : The use of a value.
2018-02-05 23:30:39 +01:00
* `Define` : The definition of a value, this is the only time when a value is set.
2016-12-02 21:09:20 +01:00
* `Scratch` : Allocate a register that can be freely modified as one wishes.
Note that `Use` ing a value decrements its `use_count` by one. When the `use_count` reaches zero the value is discarded and no longer exists.
The member functions on `RegAlloc` are just a combination of the above concepts.
### `Scratch`
Xbyak::Reg64 ScratchGpr(HostLocList desired_locations = any_gpr)
Xbyak::Xmm ScratchXmm(HostLocList desired_locations = any_xmm)
At runtime, allocate one of the registers in `desired_locations` . You are free to modify the register. The register is discarded at the end of the allocation scope.
### Pure `Use`
2018-02-05 23:30:39 +01:00
Xbyak::Reg64 UseGpr(Argument& arg);
Xbyak::Xmm UseXmm(Argument& arg);
OpArg UseOpArg(Argument& arg);
void Use(Argument& arg, HostLoc host_loc);
2016-12-02 21:09:20 +01:00
2018-02-05 23:30:39 +01:00
At runtime, the value corresponding to `arg` will be placed a register. The actual register is determined by
which one of the above functions is called. `UseGpr` places it in an unused GPR, `UseXmm` places it
in an unused XMM register, `UseOpArg` might be in a register or might be a memory location, and `Use` allows
you to specify a specific register (GPR or XMM) to use.
2016-12-02 21:09:20 +01:00
This register **must not** have it's value changed.
### `UseScratch`
2018-02-05 23:30:39 +01:00
Xbyak::Reg64 UseScratchGpr(Argument& arg);
Xbyak::Xmm UseScratchXmm(Argument& arg);
void UseScratch(Argument& arg, HostLoc host_loc);
2016-12-02 21:09:20 +01:00
2018-02-05 23:30:39 +01:00
At runtime, the value corresponding to `arg` will be placed a register. The actual register is determined by
which one of the above functions is called. `UseScratchGpr` places it in an unused GPR, `UseScratchXmm` places it
in an unused XMM register, and `UseScratch` allows you to specify a specific register (GPR or XMM) to use.
2016-12-02 21:09:20 +01:00
2018-02-05 23:30:39 +01:00
The return value is the register allocated to you.
2016-12-02 21:09:20 +01:00
2018-02-05 23:30:39 +01:00
You are free to modify the value in the register. The register is discarded at the end of the allocation scope.
2016-12-02 21:09:20 +01:00
2018-02-05 23:30:39 +01:00
### `Define` as register
2016-12-02 21:09:20 +01:00
2018-02-05 23:30:39 +01:00
A `Define` is the defintion of a value. This is the only time when a value may be set.
2016-12-02 21:09:20 +01:00
2018-02-05 23:30:39 +01:00
void DefineValue(IR::Inst* inst, const Xbyak::Reg& reg);
2016-12-02 21:09:20 +01:00
2018-02-05 23:30:39 +01:00
By calling `DefineValue` , you are stating that you wish to define the value for `inst` , and you have written the
value to the specified register `reg` .
2016-12-02 21:09:20 +01:00
2018-02-05 23:30:39 +01:00
### `Define`ing as an alias of a different value
2016-12-02 21:09:20 +01:00
2018-02-05 23:30:39 +01:00
Adding a `Define` to an existing value.
2016-12-02 21:09:20 +01:00
2018-02-05 23:30:39 +01:00
void DefineValue(IR::Inst* inst, Argument& arg);
2016-12-02 21:09:20 +01:00
2018-02-05 23:30:39 +01:00
You are declaring that the value for `inst` is the same as the value for `arg` . No host machine instructions are
emitted.
2016-12-02 21:09:20 +01:00
## When to use each?
2018-02-05 23:30:39 +01:00
* Prefer `Use` to `UseScratch` where possible.
* Prefer the `OpArg` variants where possible.
* Prefer to **not** use the specific `HostLoc` variants where possible.