In #108, we had removed a conditional that became constant-false with the removal of pinned vregs. Unfortunately, in a pretty embarrassing text-editing error, I removed the wrong end-brace and re-indented. This had the effect of moving some of the move-resolution code around in the regalloc backend, skipping moves in some cases and generating incorrect results. Caught as a fuzzbug by OSS-Fuzz in [0] (public after this merges and is detected as fixed). [0]: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=55391
This commit is contained in:
172
src/ion/moves.rs
172
src/ion/moves.rs
@@ -364,101 +364,101 @@ impl<'a, F: Function> Env<'a, F> {
|
||||
}
|
||||
|
||||
block = block.next();
|
||||
}
|
||||
|
||||
// Scan over blocks whose beginnings are covered by
|
||||
// this range and for which the vreg is live at the
|
||||
// start of the block. For each, for each predecessor,
|
||||
// add a Dest half-move.
|
||||
let mut block = self.cfginfo.insn_block[range.from.inst().index()];
|
||||
if self.cfginfo.block_entry[block.index()] < range.from {
|
||||
block = block.next();
|
||||
// Scan over blocks whose beginnings are covered by
|
||||
// this range and for which the vreg is live at the
|
||||
// start of the block. For each, for each predecessor,
|
||||
// add a Dest half-move.
|
||||
let mut block = self.cfginfo.insn_block[range.from.inst().index()];
|
||||
if self.cfginfo.block_entry[block.index()] < range.from {
|
||||
block = block.next();
|
||||
}
|
||||
while block.is_valid() && block.index() < self.func.num_blocks() {
|
||||
if self.cfginfo.block_entry[block.index()] >= range.to {
|
||||
break;
|
||||
}
|
||||
while block.is_valid() && block.index() < self.func.num_blocks() {
|
||||
if self.cfginfo.block_entry[block.index()] >= range.to {
|
||||
|
||||
// Add half-moves for blockparam inputs.
|
||||
trace!(
|
||||
"scanning blockparam_ins at vreg {} block {}: blockparam_in_idx = {}",
|
||||
vreg.index(),
|
||||
block.index(),
|
||||
blockparam_in_idx
|
||||
);
|
||||
while blockparam_in_idx < self.blockparam_ins.len() {
|
||||
let BlockparamIn {
|
||||
from_block,
|
||||
to_block,
|
||||
to_vreg,
|
||||
} = self.blockparam_ins[blockparam_in_idx];
|
||||
if (to_vreg, to_block) > (vreg, block) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Add half-moves for blockparam inputs.
|
||||
trace!(
|
||||
"scanning blockparam_ins at vreg {} block {}: blockparam_in_idx = {}",
|
||||
vreg.index(),
|
||||
block.index(),
|
||||
blockparam_in_idx
|
||||
);
|
||||
while blockparam_in_idx < self.blockparam_ins.len() {
|
||||
let BlockparamIn {
|
||||
from_block,
|
||||
to_block,
|
||||
to_vreg,
|
||||
} = self.blockparam_ins[blockparam_in_idx];
|
||||
if (to_vreg, to_block) > (vreg, block) {
|
||||
break;
|
||||
}
|
||||
if (to_vreg, to_block) == (vreg, block) {
|
||||
half_moves.push(HalfMove {
|
||||
key: half_move_key(
|
||||
from_block,
|
||||
to_block,
|
||||
to_vreg,
|
||||
HalfMoveKind::Dest,
|
||||
),
|
||||
alloc,
|
||||
});
|
||||
trace!(
|
||||
"match: blockparam_in: v{} in block{} from block{} into {}",
|
||||
to_vreg.index(),
|
||||
to_block.index(),
|
||||
from_block.index(),
|
||||
alloc,
|
||||
);
|
||||
#[cfg(debug_assertions)]
|
||||
if self.annotations_enabled {
|
||||
self.annotate(
|
||||
self.cfginfo.block_entry[block.index()],
|
||||
format!(
|
||||
"blockparam-in: block{} to block{}:into v{} in {}",
|
||||
from_block.index(),
|
||||
to_block.index(),
|
||||
to_vreg.index(),
|
||||
alloc
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
blockparam_in_idx += 1;
|
||||
}
|
||||
|
||||
if !self.is_live_in(block, vreg) {
|
||||
block = block.next();
|
||||
continue;
|
||||
}
|
||||
|
||||
trace!(
|
||||
"scanning preds at vreg {} block {} for ends outside the range",
|
||||
vreg.index(),
|
||||
block.index()
|
||||
);
|
||||
|
||||
// Now find any preds whose ends are not in the
|
||||
// same range, and insert appropriate moves.
|
||||
for &pred in self.func.block_preds(block) {
|
||||
trace!(
|
||||
"pred block {} has exit {:?}",
|
||||
pred.index(),
|
||||
self.cfginfo.block_exit[pred.index()]
|
||||
);
|
||||
if range.contains_point(self.cfginfo.block_exit[pred.index()]) {
|
||||
continue;
|
||||
}
|
||||
trace!(" -> requires half-move");
|
||||
if (to_vreg, to_block) == (vreg, block) {
|
||||
half_moves.push(HalfMove {
|
||||
key: half_move_key(pred, block, vreg, HalfMoveKind::Dest),
|
||||
key: half_move_key(
|
||||
from_block,
|
||||
to_block,
|
||||
to_vreg,
|
||||
HalfMoveKind::Dest,
|
||||
),
|
||||
alloc,
|
||||
});
|
||||
trace!(
|
||||
"match: blockparam_in: v{} in block{} from block{} into {}",
|
||||
to_vreg.index(),
|
||||
to_block.index(),
|
||||
from_block.index(),
|
||||
alloc,
|
||||
);
|
||||
#[cfg(debug_assertions)]
|
||||
if self.annotations_enabled {
|
||||
self.annotate(
|
||||
self.cfginfo.block_entry[block.index()],
|
||||
format!(
|
||||
"blockparam-in: block{} to block{}:into v{} in {}",
|
||||
from_block.index(),
|
||||
to_block.index(),
|
||||
to_vreg.index(),
|
||||
alloc
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
block = block.next();
|
||||
blockparam_in_idx += 1;
|
||||
}
|
||||
|
||||
if !self.is_live_in(block, vreg) {
|
||||
block = block.next();
|
||||
continue;
|
||||
}
|
||||
|
||||
trace!(
|
||||
"scanning preds at vreg {} block {} for ends outside the range",
|
||||
vreg.index(),
|
||||
block.index()
|
||||
);
|
||||
|
||||
// Now find any preds whose ends are not in the
|
||||
// same range, and insert appropriate moves.
|
||||
for &pred in self.func.block_preds(block) {
|
||||
trace!(
|
||||
"pred block {} has exit {:?}",
|
||||
pred.index(),
|
||||
self.cfginfo.block_exit[pred.index()]
|
||||
);
|
||||
if range.contains_point(self.cfginfo.block_exit[pred.index()]) {
|
||||
continue;
|
||||
}
|
||||
trace!(" -> requires half-move");
|
||||
half_moves.push(HalfMove {
|
||||
key: half_move_key(pred, block, vreg, HalfMoveKind::Dest),
|
||||
alloc,
|
||||
});
|
||||
}
|
||||
|
||||
block = block.next();
|
||||
}
|
||||
|
||||
// Scan over def/uses and apply allocations.
|
||||
|
||||
Reference in New Issue
Block a user