diff --git a/src/ion/dump.rs b/src/ion/dump.rs index c291253..bb1729b 100644 --- a/src/ion/dump.rs +++ b/src/ion/dump.rs @@ -1,7 +1,7 @@ //! Debugging output. use super::Env; -use crate::{Function, ProgPoint, Block}; +use crate::{Block, Function, ProgPoint}; impl<'a, F: Function> Env<'a, F> { pub fn dump_state(&self) { diff --git a/src/ion/liveranges.rs b/src/ion/liveranges.rs index 4189502..8bf48e4 100644 --- a/src/ion/liveranges.rs +++ b/src/ion/liveranges.rs @@ -272,6 +272,9 @@ impl<'a, F: Function> Env<'a, F> { for pos in &[OperandPos::After, OperandPos::Before] { for op in self.func.inst_operands(inst) { + if op.as_fixed().is_some() { + continue; + } if op.pos() == *pos { let was_live = live.get(op.vreg().vreg()); log::debug!("op {:?} was_live = {}", op, was_live); @@ -868,6 +871,15 @@ impl<'a, F: Function> Env<'a, F> { operand ); + // If this is a "fixed non-allocatable + // register" operand, set the alloc + // immediately and then ignore the operand + // hereafter. + if let Some(preg) = operand.as_fixed() { + self.set_alloc(inst, i, Allocation::reg(preg)); + continue; + } + match operand.kind() { OperandKind::Def | OperandKind::Mod => { log::debug!("Def of {} at {:?}", operand.vreg(), pos); diff --git a/src/lib.rs b/src/lib.rs index ee5afb2..5535e8d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -144,6 +144,15 @@ impl VReg { pub fn invalid() -> Self { VReg::new(Self::MAX, RegClass::Int) } + + #[inline(always)] + pub fn is_valid(self) -> bool { + self != Self::invalid() + } + #[inline(always)] + pub fn is_invalid(self) -> bool { + self == Self::invalid() + } } impl std::fmt::Debug for VReg { @@ -328,6 +337,19 @@ impl Operand { ) } + /// Create an Operand that always results in an assignment to the + /// given fixed `preg`, *without* tracking liveranges in that + /// `preg`. Must only be used for non-allocatable registers. + #[inline(always)] + pub fn fixed(preg: PReg) -> Self { + Operand::new( + VReg::invalid(), + OperandPolicy::FixedReg(preg), + OperandKind::Use, // doesn't matter + OperandPos::Before, // doesn't matter + ) + } + #[inline(always)] pub fn vreg(self) -> VReg { let vreg_idx = ((self.bits as usize) & VReg::MAX) as usize; @@ -379,6 +401,14 @@ impl Operand { } } + #[inline(always)] + pub fn as_fixed(self) -> Option { + match (self.vreg().is_invalid(), self.policy()) { + (true, OperandPolicy::FixedReg(preg)) => Some(preg), + _ => None, + } + } + #[inline(always)] pub fn bits(self) -> u32 { self.bits