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();
|
block = block.next();
|
||||||
|
}
|
||||||
|
|
||||||
// Scan over blocks whose beginnings are covered by
|
// Scan over blocks whose beginnings are covered by
|
||||||
// this range and for which the vreg is live at the
|
// this range and for which the vreg is live at the
|
||||||
// start of the block. For each, for each predecessor,
|
// start of the block. For each, for each predecessor,
|
||||||
// add a Dest half-move.
|
// add a Dest half-move.
|
||||||
let mut block = self.cfginfo.insn_block[range.from.inst().index()];
|
let mut block = self.cfginfo.insn_block[range.from.inst().index()];
|
||||||
if self.cfginfo.block_entry[block.index()] < range.from {
|
if self.cfginfo.block_entry[block.index()] < range.from {
|
||||||
block = block.next();
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
if (to_vreg, to_block) == (vreg, block) {
|
||||||
// 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");
|
|
||||||
half_moves.push(HalfMove {
|
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,
|
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;
|
||||||
block = block.next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.
|
// Scan over def/uses and apply allocations.
|
||||||
|
|||||||
Reference in New Issue
Block a user