Bugfix: process parallel moves separately for Int and Float classes
This commit is contained in:
@@ -3441,6 +3441,12 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
"insert_move: pos {:?} prio {:?} from_alloc {:?} to_alloc {:?}",
|
"insert_move: pos {:?} prio {:?} from_alloc {:?} to_alloc {:?}",
|
||||||
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 {
|
self.inserted_moves.push(InsertedMove {
|
||||||
pos,
|
pos,
|
||||||
prio,
|
prio,
|
||||||
@@ -4145,28 +4151,51 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
}
|
}
|
||||||
let moves = &self.inserted_moves[start..i];
|
let moves = &self.inserted_moves[start..i];
|
||||||
|
|
||||||
// Get the regclass from one of the moves.
|
// Gather all the moves with Int class and Float class
|
||||||
let regclass = moves[0].from_alloc.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![];
|
||||||
|
|
||||||
// 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.
|
|
||||||
let mut parallel_moves = ParallelMoves::new(Allocation::reg(
|
|
||||||
self.env.scratch_by_class[regclass as u8 as usize],
|
|
||||||
));
|
|
||||||
log::debug!("parallel moves at pos {:?} prio {:?}", pos, prio);
|
|
||||||
for m in moves {
|
for m in moves {
|
||||||
if m.from_alloc != m.to_alloc {
|
assert_eq!(m.from_alloc.class(), m.to_alloc.class());
|
||||||
log::debug!(" {} -> {}", m.from_alloc, m.to_alloc,);
|
match m.from_alloc.class() {
|
||||||
parallel_moves.add(m.from_alloc, m.to_alloc);
|
RegClass::Int => {
|
||||||
|
int_moves.push(m.clone());
|
||||||
|
}
|
||||||
|
RegClass::Float => {
|
||||||
|
float_moves.push(m.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let resolved = parallel_moves.resolve();
|
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.
|
||||||
|
let mut parallel_moves = ParallelMoves::new(Allocation::reg(
|
||||||
|
self.env.scratch_by_class[regclass as u8 as usize],
|
||||||
|
));
|
||||||
|
log::debug!("parallel moves at pos {:?} prio {:?}", pos, prio);
|
||||||
|
for m in moves {
|
||||||
|
if m.from_alloc != m.to_alloc {
|
||||||
|
log::debug!(" {} -> {}", m.from_alloc, m.to_alloc,);
|
||||||
|
parallel_moves.add(m.from_alloc, m.to_alloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (src, dst) in resolved {
|
let resolved = parallel_moves.resolve();
|
||||||
log::debug!(" resolved: {} -> {}", src, dst);
|
|
||||||
self.add_edit(pos, prio, Edit::Move { from: src, to: dst });
|
for (src, dst) in resolved {
|
||||||
|
log::debug!(" resolved: {} -> {}", src, dst);
|
||||||
|
self.add_edit(pos, prio, Edit::Move { from: src, to: dst });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4233,6 +4262,9 @@ impl<'a, F: Function> Env<'a, F> {
|
|||||||
fn add_edit(&mut self, pos: ProgPoint, prio: InsertMovePrio, edit: Edit) {
|
fn add_edit(&mut self, pos: ProgPoint, prio: InsertMovePrio, edit: Edit) {
|
||||||
match &edit {
|
match &edit {
|
||||||
&Edit::Move { from, to } if from == to => return,
|
&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());
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user