Remove register class from SpillSlot (#80)

* Remove register class from `SpillSlot`

The register allocator was already allowing moves between spillslots and
registers of different classes, so this PR formalizes this by making
spillslots independent of register class.

This also fixes #79 by properly tracking the register class of an
`InsertedMove` with the `to_vreg` field which turns out to never
be `None` in practice. Removing the `Option` allows the register
class of the `VReg` to be used when building the per-class move lists.

Fixes #79

* Address review feedback
This commit is contained in:
Amanieu d'Antras
2022-09-21 05:05:23 +08:00
committed by GitHub
parent 3db1b7199b
commit 906a053208
6 changed files with 40 additions and 74 deletions

View File

@@ -45,20 +45,21 @@ impl<'a, F: Function> Env<'a, F> {
prio: InsertMovePrio,
from_alloc: Allocation,
to_alloc: Allocation,
to_vreg: Option<VReg>,
to_vreg: VReg,
) {
trace!(
"insert_move: pos {:?} prio {:?} from_alloc {:?} to_alloc {:?}",
"insert_move: pos {:?} prio {:?} from_alloc {:?} to_alloc {:?} to_vreg {:?}",
pos,
prio,
from_alloc,
to_alloc
to_alloc,
to_vreg
);
match (from_alloc.as_reg(), to_alloc.as_reg()) {
(Some(from), Some(to)) => {
debug_assert_eq!(from.class(), to.class());
}
_ => {}
if let Some(from) = from_alloc.as_reg() {
debug_assert_eq!(from.class(), to_vreg.class());
}
if let Some(to) = to_alloc.as_reg() {
debug_assert_eq!(to.class(), to_vreg.class());
}
self.inserted_moves.push(InsertedMove {
pos_prio: PosWithPrio {
@@ -280,7 +281,7 @@ impl<'a, F: Function> Env<'a, F> {
InsertMovePrio::Regular,
prev_alloc,
alloc,
Some(self.vreg(vreg)),
self.vreg(vreg),
);
}
}
@@ -720,7 +721,7 @@ impl<'a, F: Function> Env<'a, F> {
prio,
src.alloc,
dest.alloc,
Some(self.vreg(dest.to_vreg())),
self.vreg(dest.to_vreg()),
);
last = Some(dest.alloc);
}
@@ -741,13 +742,7 @@ impl<'a, F: Function> Env<'a, F> {
FixedRegFixupLevel::Initial => InsertMovePrio::MultiFixedRegInitial,
FixedRegFixupLevel::Secondary => InsertMovePrio::MultiFixedRegSecondary,
};
self.insert_move(
fixup.pos,
prio,
from_alloc,
to_alloc,
Some(self.vreg(fixup.vreg)),
);
self.insert_move(fixup.pos, prio, from_alloc, to_alloc, self.vreg(fixup.vreg));
self.set_alloc(
fixup.pos.inst(),
fixup.to_slot as usize,
@@ -831,7 +826,7 @@ impl<'a, F: Function> Env<'a, F> {
InsertMovePrio::ReusedInput,
input_alloc,
output_alloc,
Some(input_operand.vreg()),
input_operand.vreg(),
);
self.set_alloc(inst, input_idx, output_alloc);
}
@@ -871,7 +866,7 @@ impl<'a, F: Function> Env<'a, F> {
InsertMovePrio::Regular,
from_alloc,
to_alloc,
Some(self.vreg(to_vreg)),
self.vreg(to_vreg),
);
}
@@ -961,13 +956,10 @@ impl<'a, F: Function> Env<'a, F> {
let mut float_moves: SmallVec<[InsertedMove; 8]> = smallvec![];
for m in moves {
if m.from_alloc.is_reg() && m.to_alloc.is_reg() {
debug_assert_eq!(m.from_alloc.class(), m.to_alloc.class());
}
if m.from_alloc == m.to_alloc {
continue;
}
match m.from_alloc.class() {
match m.to_vreg.class() {
RegClass::Int => {
int_moves.push(m.clone());
}
@@ -990,10 +982,8 @@ impl<'a, F: Function> Env<'a, F> {
pos_prio.prio
);
for m in moves {
if (m.from_alloc != m.to_alloc) || m.to_vreg.is_some() {
trace!(" {} -> {}", m.from_alloc, m.to_alloc,);
parallel_moves.add(m.from_alloc, m.to_alloc, m.to_vreg);
}
trace!(" {} -> {}", m.from_alloc, m.to_alloc);
parallel_moves.add(m.from_alloc, m.to_alloc, Some(m.to_vreg));
}
let resolved = parallel_moves.resolve();
@@ -1042,7 +1032,7 @@ impl<'a, F: Function> Env<'a, F> {
// these placeholders then allocate the actual
// slots if needed with `self.allocate_spillslot`
// below.
Allocation::stack(SpillSlot::new(SpillSlot::MAX - idx, regclass))
Allocation::stack(SpillSlot::new(SpillSlot::MAX - idx))
};
let is_stack_alloc = |alloc: Allocation| {
if let Some(preg) = alloc.as_reg() {
@@ -1065,11 +1055,12 @@ impl<'a, F: Function> Env<'a, F> {
let mut rewrites = FxHashMap::default();
for i in 0..stackslot_idx {
if i >= self.extra_spillslots_by_class[regclass as usize].len() {
let slot = self.allocate_spillslot(regclass);
let slot =
self.allocate_spillslot(self.func.spillslot_size(regclass) as u32);
self.extra_spillslots_by_class[regclass as usize].push(slot);
}
rewrites.insert(
Allocation::stack(SpillSlot::new(SpillSlot::MAX - i, regclass)),
Allocation::stack(SpillSlot::new(SpillSlot::MAX - i)),
self.extra_spillslots_by_class[regclass as usize][i],
);
}