diff options
author | Alon Zakai <alonzakai@gmail.com> | 2017-09-05 11:33:22 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2017-09-06 09:36:24 -0700 |
commit | 68b57f6c015af1eaf95b039b0bc2bc3b9efbab4e (patch) | |
tree | eedfada9fbc282d91bc46a5f9dd6ffc7ee1ac4c5 | |
parent | 3d1c3a3a342d4d22dcda4e45e4f4aae93b464ec8 (diff) | |
download | binaryen-68b57f6c015af1eaf95b039b0bc2bc3b9efbab4e.tar.gz binaryen-68b57f6c015af1eaf95b039b0bc2bc3b9efbab4e.tar.bz2 binaryen-68b57f6c015af1eaf95b039b0bc2bc3b9efbab4e.zip |
when if arms are identical, merging them may change the type of the if, if it has a forced type
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 29 | ||||
-rw-r--r-- | test/passes/optimize-instructions.txt | 34 | ||||
-rw-r--r-- | test/passes/optimize-instructions.wast | 21 |
3 files changed, 78 insertions, 6 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index acbf39447..0b47d3398 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -620,16 +620,33 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions, std::swap(iff->ifTrue, iff->ifFalse); } } - if (ExpressionAnalyzer::equal(iff->ifTrue, iff->ifFalse)) { + if (iff->condition->type != unreachable && ExpressionAnalyzer::equal(iff->ifTrue, iff->ifFalse)) { // sides are identical, fold - if (!EffectAnalyzer(getPassOptions(), iff->condition).hasSideEffects()) { + // if we can replace the if with one arm, and no side effects in the condition, do that + auto needCondition = EffectAnalyzer(getPassOptions(), iff->condition).hasSideEffects(); + auto typeIsIdentical = iff->ifTrue->type == iff->type; + if (typeIsIdentical && !needCondition) { return iff->ifTrue; } else { Builder builder(*getModule()); - return builder.makeSequence( - builder.makeDrop(iff->condition), - iff->ifTrue - ); + if (typeIsIdentical) { + return builder.makeSequence( + builder.makeDrop(iff->condition), + iff->ifTrue + ); + } else { + // the types diff. as the condition is reachable, that means the if must be + // concrete while the arm is not + assert(isConcreteWasmType(iff->type) && iff->ifTrue->type == unreachable); + // emit a block with a forced type + auto* ret = builder.makeBlock(); + if (needCondition) { + ret->list.push_back(builder.makeDrop(iff->condition)); + } + ret->list.push_back(iff->ifTrue); + ret->finalize(iff->type); + return ret; + } } } } diff --git a/test/passes/optimize-instructions.txt b/test/passes/optimize-instructions.txt index 6a99ee106..aae0724a0 100644 --- a/test/passes/optimize-instructions.txt +++ b/test/passes/optimize-instructions.txt @@ -1913,6 +1913,40 @@ ) ) ) + (drop + (block (result i32) + (i32.add + (get_local $1) + (unreachable) + ) + ) + ) + (drop + (block (result i32) + (drop + (tee_local $0 + (get_local $1) + ) + ) + (i32.add + (get_local $1) + (unreachable) + ) + ) + ) + (drop + (if (result i32) + (unreachable) + (i32.add + (get_local $1) + (unreachable) + ) + (i32.add + (get_local $1) + (unreachable) + ) + ) + ) ) (func $select-parallel (type $4) (param $0 i32) (param $1 i32) (drop diff --git a/test/passes/optimize-instructions.wast b/test/passes/optimize-instructions.wast index c26aad196..f84be8330 100644 --- a/test/passes/optimize-instructions.wast +++ b/test/passes/optimize-instructions.wast @@ -2321,6 +2321,27 @@ (i32.add (get_local $1) (i32.const 1)) ) ) + (drop + (if (result i32) + (get_local $0) + (i32.add (get_local $1) (unreachable)) ;; folding them would change the type of the if + (i32.add (get_local $1) (unreachable)) + ) + ) + (drop + (if (result i32) + (tee_local $0 (get_local $1)) ;; side effects! + (i32.add (get_local $1) (unreachable)) ;; folding them would change the type of the if + (i32.add (get_local $1) (unreachable)) + ) + ) + (drop + (if (result i32) + (unreachable) ;; !!! + (i32.add (get_local $1) (unreachable)) ;; folding them would change the type of the if + (i32.add (get_local $1) (unreachable)) + ) + ) ) (func $select-parallel (param $0 i32) (param $1 i32) (drop |