From 94944d20576759deadb6415d80e95e4a346bc2b6 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 11 May 2017 11:25:35 -0700 Subject: [PATCH] Keep dead EBB arguments around in LiveValueTracker::ebb_top(). Provide a drop_dead_args() function which deletes them instead. We still need to assign a register to dead EBB arguments, so they can't just be ignored. --- lib/cretonne/src/ir/layout.rs | 5 +++ lib/cretonne/src/regalloc/coloring.rs | 13 +++++- .../src/regalloc/live_value_tracker.rs | 40 ++++++++++++++----- 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/lib/cretonne/src/ir/layout.rs b/lib/cretonne/src/ir/layout.rs index b8ef83e75b..abf0f3f482 100644 --- a/lib/cretonne/src/ir/layout.rs +++ b/lib/cretonne/src/ir/layout.rs @@ -435,6 +435,11 @@ impl Layout { self.assign_inst_seq(inst); } + /// Fetch an ebb's first instruction. + pub fn first_inst(&self, ebb: Ebb) -> Option { + self.ebbs[ebb].first_inst.into() + } + /// Fetch an ebb's last instruction. pub fn last_inst(&self, ebb: Ebb) -> Option { self.ebbs[ebb].last_inst.into() diff --git a/lib/cretonne/src/regalloc/coloring.rs b/lib/cretonne/src/regalloc/coloring.rs index 871d86e757..6c0c906f90 100644 --- a/lib/cretonne/src/regalloc/coloring.rs +++ b/lib/cretonne/src/regalloc/coloring.rs @@ -129,6 +129,7 @@ impl<'a> Context<'a> { fn visit_ebb(&mut self, ebb: Ebb, func: &mut Function, tracker: &mut LiveValueTracker) { dbg!("Coloring {}:", ebb); let mut regs = self.visit_ebb_header(ebb, func, tracker); + tracker.drop_dead_args(); self.divert.clear(); // Now go through the instructions in `ebb` and color the values they define. @@ -162,14 +163,24 @@ impl<'a> Context<'a> { tracker.ebb_top(ebb, &func.dfg, self.liveness, &func.layout, self.domtree); // Arguments to the entry block have ABI constraints. - if func.layout.entry_block() == Some(ebb) { + let mut regs = if func.layout.entry_block() == Some(ebb) { assert_eq!(liveins.len(), 0); self.color_entry_args(&func.signature, args, &mut func.locations) } else { // The live-ins have already been assigned a register. Reconstruct the allocatable set. let regs = self.livein_regs(liveins, func); self.color_args(args, regs, &mut func.locations) + }; + + // Now forget about the dead arguments. + for lv in args.iter().filter(|&lv| lv.is_dead) { + if let Affinity::Reg(rci) = lv.affinity { + let rc = self.reginfo.rc(rci); + let reg = func.locations[lv.value].unwrap_reg(); + regs.free(rc, reg); + } } + regs } /// Initialize a set of allocatable registers from the values that are live-in to a block. diff --git a/lib/cretonne/src/regalloc/live_value_tracker.rs b/lib/cretonne/src/regalloc/live_value_tracker.rs index 76e2fcb0d7..a5ee8197e8 100644 --- a/lib/cretonne/src/regalloc/live_value_tracker.rs +++ b/lib/cretonne/src/regalloc/live_value_tracker.rs @@ -7,7 +7,7 @@ use dominator_tree::DominatorTree; use entity_list::{EntityList, ListPool}; use ir::instructions::BranchInfo; -use ir::{Inst, Ebb, Value, DataFlowGraph, ProgramOrder, ExpandedProgramPoint}; +use ir::{Inst, Ebb, Value, DataFlowGraph, Layout, ExpandedProgramPoint}; use partition_slice::partition_slice; use regalloc::affinity::Affinity; use regalloc::liveness::Liveness; @@ -116,6 +116,12 @@ impl LiveValueVec { let keep = self.live_after(next_inst); self.values.truncate(keep); } + + /// Remove any dead values. + fn remove_dead_values(&mut self) { + self.values.retain(|v| !v.is_dead); + self.live_prefix = None; + } } impl LiveValueTracker { @@ -150,14 +156,15 @@ impl LiveValueTracker { /// /// Returns `(liveins, args)` as a pair of slices. The first slice is the set of live-in values /// from the immediate dominator. The second slice is the set of `ebb` arguments that are live. - /// Dead arguments with no uses are ignored and not added to the set. - pub fn ebb_top(&mut self, - ebb: Ebb, - dfg: &DataFlowGraph, - liveness: &Liveness, - program_order: &PO, - domtree: &DominatorTree) - -> (&[LiveValue], &[LiveValue]) { + /// + /// Dead arguments with no uses are included in `args`. Call `drop_dead_args()` to remove them. + pub fn ebb_top(&mut self, + ebb: Ebb, + dfg: &DataFlowGraph, + liveness: &Liveness, + layout: &Layout, + domtree: &DominatorTree) + -> (&[LiveValue], &[LiveValue]) { // Start over, compute the set of live values at the top of the EBB from two sources: // // 1. Values that were live before `ebb`'s immediate dominator, filtered for those that are @@ -183,7 +190,7 @@ impl LiveValueTracker { .expect("Immediate dominator value has no live range"); // Check if this value is live-in here. - if let Some(endpoint) = lr.livein_local_end(ebb, program_order) { + if let Some(endpoint) = lr.livein_local_end(ebb, layout) { self.live.push(value, endpoint, lr); } } @@ -202,10 +209,14 @@ impl LiveValueTracker { } ExpandedProgramPoint::Ebb(local_ebb) => { // This is a dead EBB argument which is not even live into the first - // instruction in the EBB. We can ignore it. + // instruction in the EBB. assert_eq!(local_ebb, ebb, "EBB argument live range ends at wrong EBB header"); + // Give this value a fake endpoint that is the first instruction in the EBB. + // We expect it to be removed by calling `drop_dead_args()`. + self.live + .push(value, layout.first_inst(ebb).expect("Empty EBB"), lr); } } } @@ -281,6 +292,13 @@ impl LiveValueTracker { self.live.remove_kill_values(inst); } + /// Drop any values that are marked as `is_dead`. + /// + /// Use this after calling `ebb_top` to clean out dead EBB arguments. + pub fn drop_dead_args(&mut self) { + self.live.remove_dead_values(); + } + /// Save the current set of live values so it is associated with `idom`. fn save_idom_live_set(&mut self, idom: Inst) { let values = self.live.values.iter().map(|lv| lv.value);