From 7d748241d3c69d0d87cf8d78174f174c234e406e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 14 Sep 2016 14:01:21 -0700 Subject: when optimizing a block return value, replacing the sunk set with the value is only possible if the break is unconditional; if it is condition, we must tee the value so that if the break condition is false and we do not jump, then we have the new value in the local on the line after it --- src/passes/SimplifyLocals.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'src/passes/SimplifyLocals.cpp') diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp index efc73aa29..e032acc77 100644 --- a/src/passes/SimplifyLocals.cpp +++ b/src/passes/SimplifyLocals.cpp @@ -102,8 +102,8 @@ struct SimplifyLocals : public WalkerPass> blockBreaks; - // blocks that are the targets of a switch; we need to know this - // since we can't produce a block return value for them. + // blocks that we can't produce a block return value for them. + // (switch target, or some other reason) std::set unoptimizableBlocks; // A stack of sinkables from the current traversal state. When @@ -328,9 +328,18 @@ struct SimplifyLocals : public WalkerPassvalue); - breaks[j].br->value = (*breakSetLocalPointer)->cast()->value; - ExpressionManipulator::nop(*breakSetLocalPointer); + auto* br = breaks[j].br; + assert(!br->value); + // if the break is conditional, then we must set the value here - if the break is not taken, we must still have the new value in the local + auto* set = (*breakSetLocalPointer)->cast(); + if (br->condition) { + br->value = set; + set->setTee(true); + *breakSetLocalPointer = getModule()->allocator.alloc(); + } else { + br->value = set->value; + ExpressionManipulator::nop(set); + } } // finally, create a set_local on the block itself auto* newSetLocal = Builder(*getModule()).makeSetLocal(sharedIndex, block); -- cgit v1.2.3