peepmatic: Fix a failed assertion due to extra iterations after fixed point

After replacing an instruction with an alias to an earlier value, trying to
further optimize that value is unnecessary, since we've already processed it,
and also was triggering an assertion.
This commit is contained in:
Nick Fitzgerald
2020-05-07 17:13:03 -07:00
parent eb2dab0aa4
commit 6e135b3aea
2 changed files with 34 additions and 2 deletions

View File

@@ -611,8 +611,26 @@ pub fn do_preopt<'func, 'isa>(
while let Some(block) = pos.next_block() { while let Some(block) = pos.next_block() {
while let Some(inst) = pos.next_inst() { while let Some(inst) = pos.next_inst() {
preopt.apply_all(&mut pos, ValueOrInst::Inst(inst)); // After we apply one optimization, that might make another
let inst = pos.current_inst().unwrap(); // optimization applicable. Keep running the peephole optimizer
// until either:
//
// * No optimization applied, and therefore it doesn't make sense to
// try again, because no optimization will apply again.
//
// * Or when we replaced an instruction with an alias to an existing
// value, because we already ran the peephole optimizer over the
// aliased value's instruction in an early part of the traversal
// over the function.
while let Some(ValueOrInst::Inst(new_inst)) =
preopt.apply_one(&mut pos, ValueOrInst::Inst(inst))
{
// We transplanted a new instruction into the current
// instruction, so the "new" instruction is actually the same
// one, just with different data.
debug_assert_eq!(new_inst, inst);
}
debug_assert_eq!(pos.current_inst(), Some(inst));
// Try to transform divide-by-constant into simpler operations. // Try to transform divide-by-constant into simpler operations.
if let Some(divrem_info) = get_div_info(inst, &pos.func.dfg) { if let Some(divrem_info) = get_div_info(inst, &pos.func.dfg) {

View File

@@ -0,0 +1,14 @@
test simple_preopt
target x86_64
;; This file used to trigger assertions where we would keep trying to
;; unnecessarily apply optimizations after replacing an instruction with an
;; alias of another value that we had already optimized.
function %foo() {
block0:
v0 = iconst.i32 3
v1 = srem_imm v0, 2
v2 = sdiv_imm v1, 1
trap unreachable
}