diff --git a/src/ion/liveranges.rs b/src/ion/liveranges.rs index 4189502..04ca41e 100644 --- a/src/ion/liveranges.rs +++ b/src/ion/liveranges.rs @@ -955,9 +955,11 @@ impl<'a, F: Function> Env<'a, F> { } if self.func.is_safepoint(inst) { + log::debug!("inst{} is safepoint", inst.index()); self.safepoints.push(inst); for vreg in live.iter() { if let Some(safepoints) = self.safepoints_per_vreg.get_mut(&vreg) { + log::debug!("vreg v{} live at safepoint inst{}", vreg, inst.index()); safepoints.insert(inst); } } diff --git a/src/ion/process.rs b/src/ion/process.rs index 426e7fc..ef72956 100644 --- a/src/ion/process.rs +++ b/src/ion/process.rs @@ -363,6 +363,29 @@ impl<'a, F: Function> Env<'a, F> { } } + pub fn find_conflict_split_point(&self, bundle: LiveBundleIndex) -> ProgPoint { + // Find the first use whose requirement causes the merge up to + // this point to go to Conflict. + let mut req = Requirement::Unknown; + for entry in &self.bundles[bundle.index()].ranges { + for u in &self.ranges[entry.index.index()].uses { + let this_req = Requirement::from_operand(u.operand); + req = req.merge(this_req); + if req == Requirement::Conflict { + return u.pos; + } + } + } + + // Fallback: start of bundle. + self.bundles[bundle.index()] + .ranges + .first() + .unwrap() + .range + .from + } + pub fn get_or_create_spill_bundle( &mut self, bundle: LiveBundleIndex, @@ -734,15 +757,17 @@ impl<'a, F: Function> Env<'a, F> { log::debug!("process_bundle: bundle {:?} hint {:?}", bundle, hint_reg,); if let Requirement::Conflict = req { - // We have to split right away. + // We have to split right away. We'll find a point to + // split that would allow at least the first half of the + // split to be conflict-free. assert!( !self.minimal_bundle(bundle), "Minimal bundle with conflict!" ); - let bundle_start = self.bundles[bundle.index()].ranges[0].range.from; + let split_point = self.find_conflict_split_point(bundle); self.split_and_requeue_bundle( bundle, - /* split_at_point = */ bundle_start, + /* split_at_point = */ split_point, reg_hint, ); return Ok(());