diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-09-14 14:01:21 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2016-09-14 14:01:21 -0700 |
commit | 7d748241d3c69d0d87cf8d78174f174c234e406e (patch) | |
tree | 7b8dc5103c8b367573722164cdedddd87f6342a3 /src/passes/SimplifyLocals.cpp | |
parent | d8f45bca8141f6d4dcd46c46ef354756728848c6 (diff) | |
download | binaryen-7d748241d3c69d0d87cf8d78174f174c234e406e.tar.gz binaryen-7d748241d3c69d0d87cf8d78174f174c234e406e.tar.bz2 binaryen-7d748241d3c69d0d87cf8d78174f174c234e406e.zip |
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
Diffstat (limited to 'src/passes/SimplifyLocals.cpp')
-rw-r--r-- | src/passes/SimplifyLocals.cpp | 19 |
1 files changed, 14 insertions, 5 deletions
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<LinearExecutionWalker<SimplifyLocals, // block returns std::map<Name, std::vector<BlockBreak>> 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<Name> unoptimizableBlocks; // A stack of sinkables from the current traversal state. When @@ -328,9 +328,18 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals, for (size_t j = 0; j < breaks.size(); j++) { // move break set_local's value to the break auto* breakSetLocalPointer = breaks[j].sinkables.at(sharedIndex).item; - assert(!breaks[j].br->value); - breaks[j].br->value = (*breakSetLocalPointer)->cast<SetLocal>()->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<SetLocal>(); + if (br->condition) { + br->value = set; + set->setTee(true); + *breakSetLocalPointer = getModule()->allocator.alloc<Nop>(); + } else { + br->value = set->value; + ExpressionManipulator::nop(set); + } } // finally, create a set_local on the block itself auto* newSetLocal = Builder(*getModule()).makeSetLocal(sharedIndex, block); |