Bugfix: process parallel moves separately for Int and Float classes

This commit is contained in:
Chris Fallin
2021-05-08 16:16:30 -07:00
parent 179ef0e534
commit 3d0d760c70

View File

@@ -3441,6 +3441,12 @@ impl<'a, F: Function> Env<'a, F> {
"insert_move: pos {:?} prio {:?} from_alloc {:?} to_alloc {:?}",
pos, prio, from_alloc, to_alloc
);
match (from_alloc.as_reg(), to_alloc.as_reg()) {
(Some(from), Some(to)) => {
assert_eq!(from.class(), to.class());
}
_ => {}
}
self.inserted_moves.push(InsertedMove {
pos,
prio,
@@ -4145,9 +4151,31 @@ impl<'a, F: Function> Env<'a, F> {
}
let moves = &self.inserted_moves[start..i];
// Get the regclass from one of the moves.
let regclass = moves[0].from_alloc.class();
// Gather all the moves with Int class and Float class
// separately. These cannot interact, so it is safe to
// have two separate ParallelMove instances. They need to
// be separate because moves between the two classes are
// impossible. (We could enhance ParallelMoves to
// understand register classes and take multiple scratch
// regs, but this seems simpler.)
let mut int_moves: SmallVec<[InsertedMove; 8]> = smallvec![];
let mut float_moves: SmallVec<[InsertedMove; 8]> = smallvec![];
for m in moves {
assert_eq!(m.from_alloc.class(), m.to_alloc.class());
match m.from_alloc.class() {
RegClass::Int => {
int_moves.push(m.clone());
}
RegClass::Float => {
float_moves.push(m.clone());
}
}
}
for &(regclass, moves) in
&[(RegClass::Int, &int_moves), (RegClass::Float, &float_moves)]
{
// All moves in `moves` semantically happen in
// parallel. Let's resolve these to a sequence of moves
// that can be done one at a time.
@@ -4169,6 +4197,7 @@ impl<'a, F: Function> Env<'a, F> {
self.add_edit(pos, prio, Edit::Move { from: src, to: dst });
}
}
}
// Add edits to describe blockparam locations too. This is
// required by the checker. This comes after any edge-moves.
@@ -4233,6 +4262,9 @@ impl<'a, F: Function> Env<'a, F> {
fn add_edit(&mut self, pos: ProgPoint, prio: InsertMovePrio, edit: Edit) {
match &edit {
&Edit::Move { from, to } if from == to => return,
&Edit::Move { from, to } if from.is_reg() && to.is_reg() => {
assert_eq!(from.as_reg().unwrap().class(), to.as_reg().unwrap().class());
}
_ => {}
}