summaryrefslogtreecommitdiff
path: root/src/passes/SimplifyLocals.cpp
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-09-14 14:01:21 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-09-14 14:01:21 -0700
commit7d748241d3c69d0d87cf8d78174f174c234e406e (patch)
tree7b8dc5103c8b367573722164cdedddd87f6342a3 /src/passes/SimplifyLocals.cpp
parentd8f45bca8141f6d4dcd46c46ef354756728848c6 (diff)
downloadbinaryen-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.cpp19
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);