diff --git a/src/ion/liveranges.rs b/src/ion/liveranges.rs index 9508503..13c352b 100644 --- a/src/ion/liveranges.rs +++ b/src/ion/liveranges.rs @@ -943,11 +943,13 @@ impl<'a, F: Function> Env<'a, F> { OperandKind::Mod => self.cfginfo.block_entry[block.index()], _ => unreachable!(), }; - let to = match operand.kind() { - OperandKind::Def => pos.next(), - OperandKind::Mod => pos.next().next(), // both Before and After positions - _ => unreachable!(), - }; + // We want to we want to span + // until Before of the next + // inst. This ensures that early + // defs used for temps on an + // instruction are reserved across + // the whole instruction. + let to = ProgPoint::before(pos.inst().next()); lr = self.add_liverange_to_vreg( VRegIndex::new(operand.vreg().vreg()), CodeRange { from, to }, diff --git a/src/lib.rs b/src/lib.rs index 39aa101..ef350a0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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(