diff options
author | Alon Zakai <alonzakai@gmail.com> | 2017-09-05 19:26:19 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-05 19:26:19 -0700 |
commit | c0f21e10a1166829afd34c4fb06366d7430802bb (patch) | |
tree | 518bbe8c8746679b3adf678940e52158e77b5ede /src/passes | |
parent | 4f58e1e666cff6f1e61d888279dba42d1be14251 (diff) | |
download | binaryen-c0f21e10a1166829afd34c4fb06366d7430802bb.tar.gz binaryen-c0f21e10a1166829afd34c4fb06366d7430802bb.tar.bz2 binaryen-c0f21e10a1166829afd34c4fb06366d7430802bb.zip |
Return to more structured type rules for block and if (#1148)
* if a block has a concrete final element (or a break with a value), then even if it has an unreachable child, keep it with that concrete type. this means we no longe allow the silly case of a block with an unreachable in the middle and a concrete as the final element while the block is unreachable - after this change, the block would have the type of the final element
* if an if has a concrete element in one arm, make it have that type as a result, even if the if condition is unreachable, to parallel block
* make type rules for brs and switches simpler, ignore whether they are reachable or not. whether they are dead code should not affect how they influence other types in our IR.
Diffstat (limited to 'src/passes')
-rw-r--r-- | src/passes/FlattenControlFlow.cpp | 7 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 8 | ||||
-rw-r--r-- | src/passes/RemoveUnusedBrs.cpp | 4 | ||||
-rw-r--r-- | src/passes/SimplifyLocals.cpp | 5 |
4 files changed, 20 insertions, 4 deletions
diff --git a/src/passes/FlattenControlFlow.cpp b/src/passes/FlattenControlFlow.cpp index 3da5809c3..dce8e6345 100644 --- a/src/passes/FlattenControlFlow.cpp +++ b/src/passes/FlattenControlFlow.cpp @@ -61,7 +61,7 @@ #include <wasm.h> #include <pass.h> #include <wasm-builder.h> - +#include <ast_utils.h> namespace wasm { @@ -461,6 +461,11 @@ struct FlattenControlFlow : public WalkerPass<PostWalker<FlattenControlFlow>> { splitter.note(operand); } } + + void visitFunction(Function* curr) { + // removing breaks can alter types + ReFinalize().walkFunctionInModule(curr, getModule()); + } }; Pass *createFlattenControlFlowPass() { diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index f458a58b2..acbf39447 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -397,6 +397,14 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions, // Optimizations that don't yet fit in the pattern DSL, but could be eventually maybe Expression* handOptimize(Expression* curr) { + // if this contains dead code, don't bother trying to optimize it, the type + // might change (if might not be unreachable if just one arm is, for example). + // this optimization pass focuses on actually executing code. the only + // exceptions are control flow changes + if (curr->type == unreachable && + !curr->is<Break>() && !curr->is<Switch>() && !curr->is<If>()) { + return nullptr; + } if (auto* binary = curr->dynCast<Binary>()) { if (Properties::isSymmetric(binary)) { // canonicalize a const to the second position diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp index e307ec414..ec7809f48 100644 --- a/src/passes/RemoveUnusedBrs.cpp +++ b/src/passes/RemoveUnusedBrs.cpp @@ -394,7 +394,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { if (list.size() == 1 && curr->name.is()) { // if this block has just one child, a sub-block, then jumps to the former are jumps to us, really if (auto* child = list[0]->dynCast<Block>()) { - if (child->name.is() && child->name != curr->name) { + // the two blocks must have the same type for us to update the branch, as otherwise + // one block may be unreachable and the other concrete, so one might lack a value + if (child->name.is() && child->name != curr->name && child->type == curr->type) { auto& breaks = breaksToBlock[child]; for (auto* br : breaks) { newNames[br] = curr->name; diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp index 2d4a02337..919784cdf 100644 --- a/src/passes/SimplifyLocals.cpp +++ b/src/passes/SimplifyLocals.cpp @@ -372,8 +372,9 @@ struct SimplifyLocals : public WalkerPass<LinearExecutionWalker<SimplifyLocals>> // optimize set_locals from both sides of an if into a return value void optimizeIfReturn(If* iff, Expression** currp, Sinkables& ifTrue) { assert(iff->ifFalse); - // if this if already has a result, we can't do anything - if (isConcreteWasmType(iff->type)) return; + // if this if already has a result, or is unreachable code, we have + // nothing to do + if (iff->type != none) return; // We now have the sinkables from both sides of the if. Sinkables& ifFalse = sinkables; Index sharedIndex = -1; |