Track register pressure for dead EBB parameters.
The spiller wasn't tracking register pressure correctly for dead EBB parameters in visit_ebb_header(). Make sure we free any dead EBB parameters. Fixes #223
This commit is contained in:
@@ -158,7 +158,7 @@ impl<'a> Context<'a> {
|
||||
fn visit_ebb(&mut self, ebb: Ebb, tracker: &mut LiveValueTracker) {
|
||||
dbg!("Coloring {}:", ebb);
|
||||
let mut regs = self.visit_ebb_header(ebb, tracker);
|
||||
tracker.drop_dead_args();
|
||||
tracker.drop_dead_params();
|
||||
self.divert.clear();
|
||||
|
||||
// Now go through the instructions in `ebb` and color the values they define.
|
||||
|
||||
@@ -160,9 +160,9 @@ impl LiveValueTracker {
|
||||
/// been visited first.
|
||||
///
|
||||
/// 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.
|
||||
/// from the immediate dominator. The second slice is the set of `ebb` parameters.
|
||||
///
|
||||
/// Dead arguments with no uses are included in `args`. Call `drop_dead_args()` to remove them.
|
||||
/// Dead parameters with no uses are included in `args`. Call `drop_dead_args()` to remove them.
|
||||
pub fn ebb_top(
|
||||
&mut self,
|
||||
ebb: Ebb,
|
||||
@@ -314,8 +314,8 @@ impl LiveValueTracker {
|
||||
|
||||
/// 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) {
|
||||
/// Use this after calling `ebb_top` to clean out dead EBB parameters.
|
||||
pub fn drop_dead_params(&mut self) {
|
||||
self.live.remove_dead_values();
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ impl<'a> Context<'a> {
|
||||
fn visit_ebb(&mut self, ebb: Ebb, tracker: &mut LiveValueTracker) {
|
||||
dbg!("Reloading {}:", ebb);
|
||||
self.visit_ebb_header(ebb, tracker);
|
||||
tracker.drop_dead_args();
|
||||
tracker.drop_dead_params();
|
||||
|
||||
// visit_ebb_header() places us at the first interesting instruction in the EBB.
|
||||
while let Some(inst) = self.cur.current_inst() {
|
||||
|
||||
@@ -120,7 +120,8 @@ impl<'a> Context<'a> {
|
||||
dbg!("Spilling {}:", ebb);
|
||||
self.cur.goto_top(ebb);
|
||||
self.visit_ebb_header(ebb, tracker);
|
||||
tracker.drop_dead_args();
|
||||
tracker.drop_dead_params();
|
||||
self.process_spills(tracker);
|
||||
|
||||
while let Some(inst) = self.cur.next_inst() {
|
||||
if let Some(constraints) =
|
||||
@@ -163,8 +164,22 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// Free all dead registers in `regs` from the pressure set.
|
||||
fn free_dead_regs(&mut self, regs: &[LiveValue]) {
|
||||
for lv in regs {
|
||||
if lv.is_dead {
|
||||
if let Affinity::Reg(rci) = lv.affinity {
|
||||
if !self.spills.contains(&lv.value) {
|
||||
let rc = self.reginfo.rc(rci);
|
||||
self.pressure.free(rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ebb_header(&mut self, ebb: Ebb, tracker: &mut LiveValueTracker) {
|
||||
let (liveins, args) = tracker.ebb_top(
|
||||
let (liveins, params) = tracker.ebb_top(
|
||||
ebb,
|
||||
&self.cur.func.dfg,
|
||||
self.liveness,
|
||||
@@ -177,22 +192,17 @@ impl<'a> Context<'a> {
|
||||
self.pressure.reset();
|
||||
self.take_live_regs(liveins);
|
||||
|
||||
// An EBB can have an arbitrary (up to 2^16...) number of EBB arguments, so they are not
|
||||
// An EBB can have an arbitrary (up to 2^16...) number of parameters, so they are not
|
||||
// guaranteed to fit in registers.
|
||||
for lv in args {
|
||||
for lv in params {
|
||||
if let Affinity::Reg(rci) = lv.affinity {
|
||||
let rc = self.reginfo.rc(rci);
|
||||
'try_take: while let Err(mask) = self.pressure.take_transient(rc) {
|
||||
dbg!(
|
||||
"Need {} reg for EBB argument {} from {} live-ins",
|
||||
rc,
|
||||
lv.value,
|
||||
liveins.len()
|
||||
);
|
||||
dbg!("Need {} reg for EBB param {}", rc, lv.value);
|
||||
match self.spill_candidate(mask, liveins) {
|
||||
Some(cand) => {
|
||||
dbg!(
|
||||
"Spilling live-in {} to make room for {} EBB argument {}",
|
||||
"Spilling live-in {} to make room for {} EBB param {}",
|
||||
cand,
|
||||
rc,
|
||||
lv.value
|
||||
@@ -217,6 +227,7 @@ impl<'a> Context<'a> {
|
||||
|
||||
// The transient pressure counts for the EBB arguments are accurate. Just preserve them.
|
||||
self.pressure.preserve_transient();
|
||||
self.free_dead_regs(params);
|
||||
}
|
||||
|
||||
fn visit_inst(
|
||||
|
||||
Reference in New Issue
Block a user