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:
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user