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.
This commit is contained in:
Jakob Stoklund Olesen
2017-05-11 11:25:35 -07:00
parent 2c0d4136b0
commit 94944d2057
3 changed files with 46 additions and 12 deletions

View File

@@ -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<Inst> {
self.ebbs[ebb].first_inst.into()
}
/// Fetch an ebb's last instruction.
pub fn last_inst(&self, ebb: Ebb) -> Option<Inst> {
self.ebbs[ebb].last_inst.into()

View File

@@ -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,15 +163,25 @@ 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.
/// These values must already be colored when the dominating blocks were processed.

View File

@@ -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,12 +156,13 @@ 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<PO: ProgramOrder>(&mut self,
///
/// 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,
program_order: &PO,
layout: &Layout,
domtree: &DominatorTree)
-> (&[LiveValue], &[LiveValue]) {
// Start over, compute the set of live values at the top of the EBB from two sources:
@@ -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);