Early defs reserve a register for whole instruction. (#32)
The `Operand` abstraction allows a def to be positioned at the "early" point of an instruction, before its effect and alongside its normal uses. This is intended to allow the embedder to express that a def may be written before all uses are read, so it should not conflict with the uses. It's also convenient to use early defs to express temporaries, which should be available throughout a regalloc-level instruction's emitted sequence. In such a case, the register should not be used again after the instruction, so it is dead following the instruction. Strictly speaking, and according to regalloc2 prior to this PR, then the temp will *only* conflict with the uses at the early-point, and not the defs at the late-point (after the instruction), because it's dead past its point of definition. But for a temp we really want it to register conflicts not just with the normal uses but with the normal defs as well. This PR changes the semantics so that an early def builds a liverange that spans the early- and late-point of an instruction when the vreg is dead flowing down from the instruction, giving the semantics we want for temps.
This commit is contained in:
@@ -486,6 +486,13 @@ impl Operand {
|
||||
/// that must be in a register, and that occurs early at the
|
||||
/// "before" point, i.e., must not conflict with any input to the
|
||||
/// instruction.
|
||||
///
|
||||
/// Note that the register allocator will ensure that such an
|
||||
/// early-def operand is live throughout the instruction, i.e., also
|
||||
/// at the after-point. Hence it will also avoid conflicts with all
|
||||
/// outputs to the instruction. As such, early defs are appropriate
|
||||
/// for use as "temporary registers" that an instruction can use
|
||||
/// throughout its execution separately from the inputs and outputs.
|
||||
#[inline(always)]
|
||||
pub fn reg_def_at_start(vreg: VReg) -> Self {
|
||||
Operand::new(
|
||||
|
||||
Reference in New Issue
Block a user