Alloc spillsets for whole vreg, not just spilled LRs. This is a prerequisite to allowing a "clean" value to remain in spillslot while also in reg and avoiding the re-spill. It should also reduce stack-to-stack moves (though they can still come from progmoves).

This commit is contained in:
Chris Fallin
2021-05-25 18:19:25 -07:00
parent ca5f24f6b7
commit b3dc2b25a5

View File

@@ -268,11 +268,12 @@ impl LiveBundle {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct SpillSet { struct SpillSet {
bundles: SmallVec<[LiveBundleIndex; 2]>, vregs: SmallVec<[VRegIndex; 2]>,
slot: SpillSlotIndex, slot: SpillSlotIndex,
reg_hint: PReg, reg_hint: PReg,
class: RegClass, class: RegClass,
spill_bundle: LiveBundleIndex, spill_bundle: LiveBundleIndex,
required: bool,
size: u8, size: u8,
} }
@@ -2158,6 +2159,19 @@ impl<'a, F: Function> Env<'a, F> {
self.bundles[to.index()].ranges = merged; self.bundles[to.index()].ranges = merged;
self.bundles[from.index()].ranges.clear(); self.bundles[from.index()].ranges.clear();
if self.bundles[from.index()].spillset != self.bundles[to.index()].spillset {
let from_vregs = std::mem::replace(
&mut self.spillsets[self.bundles[from.index()].spillset.index()].vregs,
smallvec![],
);
let to_vregs = &mut self.spillsets[self.bundles[to.index()].spillset.index()].vregs;
for vreg in from_vregs {
if !to_vregs.contains(&vreg) {
to_vregs.push(vreg);
}
}
}
true true
} }
@@ -2204,9 +2218,10 @@ impl<'a, F: Function> Env<'a, F> {
let reg = self.vreg_regs[vreg.index()]; let reg = self.vreg_regs[vreg.index()];
let size = self.func.spillslot_size(reg.class(), reg) as u8; let size = self.func.spillslot_size(reg.class(), reg) as u8;
self.spillsets.push(SpillSet { self.spillsets.push(SpillSet {
bundles: smallvec![], vregs: smallvec![vreg],
slot: SpillSlotIndex::invalid(), slot: SpillSlotIndex::invalid(),
size, size,
required: false,
class: reg.class(), class: reg.class(),
reg_hint: PReg::invalid(), reg_hint: PReg::invalid(),
spill_bundle: LiveBundleIndex::invalid(), spill_bundle: LiveBundleIndex::invalid(),
@@ -3035,11 +3050,9 @@ impl<'a, F: Function> Env<'a, F> {
} }
Requirement::Stack(_) => { Requirement::Stack(_) => {
// If we must be on the stack, put ourselves on // If we must be on the stack, mark our spillset
// the spillset's list immediately. // as required immediately.
self.spillsets[self.bundles[bundle.index()].spillset.index()] self.spillsets[self.bundles[bundle.index()].spillset.index()].required = true;
.bundles
.push(bundle);
return Ok(()); return Ok(());
} }
@@ -3195,13 +3208,11 @@ impl<'a, F: Function> Env<'a, F> {
} }
if !success { if !success {
log::debug!( log::debug!(
"spilling bundle {:?} to spillset bundle list {:?}", "spilling bundle {:?}: marking spillset {:?} as required",
bundle, bundle,
self.bundles[bundle.index()].spillset self.bundles[bundle.index()].spillset
); );
self.spillsets[self.bundles[bundle.index()].spillset.index()] self.spillsets[self.bundles[bundle.index()].spillset.index()].required = true;
.bundles
.push(bundle);
} }
} }
} }
@@ -3211,8 +3222,8 @@ impl<'a, F: Function> Env<'a, F> {
spillslot: SpillSlotIndex, spillslot: SpillSlotIndex,
spillset: SpillSetIndex, spillset: SpillSetIndex,
) -> bool { ) -> bool {
for &bundle in &self.spillsets[spillset.index()].bundles { for &vreg in &self.spillsets[spillset.index()].vregs {
for entry in &self.bundles[bundle.index()].ranges { for entry in &self.vregs[vreg.index()].ranges {
if self.spillslots[spillslot.index()] if self.spillslots[spillslot.index()]
.ranges .ranges
.btree .btree
@@ -3231,22 +3242,22 @@ impl<'a, F: Function> Env<'a, F> {
spillslot: SpillSlotIndex, spillslot: SpillSlotIndex,
) { ) {
self.spillsets[spillset.index()].slot = spillslot; self.spillsets[spillset.index()].slot = spillslot;
for i in 0..self.spillsets[spillset.index()].bundles.len() { for i in 0..self.spillsets[spillset.index()].vregs.len() {
// don't borrow self // don't borrow self
let bundle = self.spillsets[spillset.index()].bundles[i]; let vreg = self.spillsets[spillset.index()].vregs[i];
log::debug!( log::debug!(
"spillslot {:?} alloc'ed to spillset {:?}: bundle {:?}", "spillslot {:?} alloc'ed to spillset {:?}: vreg {:?}",
spillslot, spillslot,
spillset, spillset,
bundle vreg,
); );
for entry in &self.bundles[bundle.index()].ranges { for entry in &self.vregs[vreg.index()].ranges {
log::debug!( log::debug!(
"spillslot {:?} getting range {:?} from bundle {:?}: {:?}", "spillslot {:?} getting range {:?} from LR {:?} from vreg {:?}",
spillslot, spillslot,
entry.range, entry.range,
entry.index, entry.index,
bundle, vreg,
); );
self.spillslots[spillslot.index()] self.spillslots[spillslot.index()]
.ranges .ranges
@@ -3260,7 +3271,7 @@ impl<'a, F: Function> Env<'a, F> {
for spillset in 0..self.spillsets.len() { for spillset in 0..self.spillsets.len() {
log::debug!("allocate spillslot: {}", spillset); log::debug!("allocate spillslot: {}", spillset);
let spillset = SpillSetIndex::new(spillset); let spillset = SpillSetIndex::new(spillset);
if self.spillsets[spillset.index()].bundles.is_empty() { if !self.spillsets[spillset.index()].required {
continue; continue;
} }
// Get or create the spillslot list for this size. // Get or create the spillslot list for this size.