diff --git a/lib/cretonne/src/regalloc/liveness.rs b/lib/cretonne/src/regalloc/liveness.rs index f2c9944d4b..3ced8ebc00 100644 --- a/lib/cretonne/src/regalloc/liveness.rs +++ b/lib/cretonne/src/regalloc/liveness.rs @@ -177,7 +177,7 @@ use flowgraph::ControlFlowGraph; use ir::dfg::ValueDef; -use ir::{Function, Value, Inst, Ebb}; +use ir::{Function, Value, Inst, Ebb, Layout, ProgramPoint}; use isa::{TargetIsa, EncInfo}; use regalloc::affinity::Affinity; use regalloc::liverange::LiveRange; @@ -297,6 +297,47 @@ impl Liveness { self.ranges.get(value) } + /// Create a new live range for `value`. + /// + /// The new live range will be defined at `def` with no extent, like a dead value. + /// + /// This asserts that `value` does not have an existing live range. + pub fn create_dead(&mut self, value: Value, def: PP, affinity: Affinity) + where PP: Into + { + let old = self.ranges + .insert(LiveRange::new(value, def.into(), affinity)); + assert!(old.is_none(), "{} already has a live range", value); + } + + /// Move the definition of `value` to `def`. + /// + /// The old and new def points must be in the same EBB, and before the end of the live range. + pub fn move_def_locally(&mut self, value: Value, def: PP) + where PP: Into + { + let mut lr = self.ranges.get_mut(value).expect("Value has no live range"); + lr.move_def_locally(def.into()); + } + + /// Locally extend the live range for `value` to reach `user`. + /// + /// It is assumed the `value` is already live before `user` in `ebb`. + /// + /// Returns a mutable reference to the value's affinity in case that also needs to be updated. + pub fn extend_locally(&mut self, + value: Value, + ebb: Ebb, + user: Inst, + layout: &Layout) + -> &mut Affinity { + debug_assert_eq!(Some(ebb), layout.inst_ebb(user)); + let mut lr = self.ranges.get_mut(value).expect("Value has no live range"); + let livein = lr.extend_in_ebb(ebb, user, layout); + assert!(!livein, "{} should already be live in {}", value, ebb); + &mut lr.affinity + } + /// Compute the live ranges of all SSA values used in `func`. /// This clears out any existing analysis stored in this data structure. pub fn compute(&mut self, isa: &TargetIsa, func: &Function, cfg: &ControlFlowGraph) { diff --git a/lib/cretonne/src/regalloc/liverange.rs b/lib/cretonne/src/regalloc/liverange.rs index a854cfc9ea..1cabd113dd 100644 --- a/lib/cretonne/src/regalloc/liverange.rs +++ b/lib/cretonne/src/regalloc/liverange.rs @@ -347,6 +347,14 @@ impl LiveRange { self.def_begin } + /// Move the definition of this value to a new program point. + /// + /// It is only valid to move the definition within the same EBB, and it can't be moved beyond + /// `def_local_end()`. + pub fn move_def_locally(&mut self, def: ProgramPoint) { + self.def_begin = def; + } + /// Get the local end-point of this live range in the EBB where it is defined. /// /// This can be the EBB header itself in the case of a dead EBB argument.