diff options
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 39 | ||||
-rw-r--r-- | test/passes/O.bin.txt | 9 | ||||
-rw-r--r-- | test/passes/optimize-instructions.txt | 82 | ||||
-rw-r--r-- | test/passes/optimize-instructions.wast | 58 | ||||
-rw-r--r-- | test/wasm-only.fromasm | 23 | ||||
-rw-r--r-- | test/wasm-only.fromasm.clamp | 23 | ||||
-rw-r--r-- | test/wasm-only.fromasm.imprecise | 23 |
7 files changed, 190 insertions, 67 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index c1787b57d..50a7c5589 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -596,6 +596,18 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions, std::swap(iff->ifTrue, iff->ifFalse); } } + if (ExpressionAnalyzer::equal(iff->ifTrue, iff->ifFalse)) { + // sides are identical, fold + if (!EffectAnalyzer(getPassOptions(), iff->condition).hasSideEffects()) { + return iff->ifTrue; + } else { + Builder builder(*getModule()); + return builder.makeSequence( + builder.makeDrop(iff->condition), + iff->ifTrue + ); + } + } } } else if (auto* select = curr->dynCast<Select>()) { select->condition = optimizeBoolean(select->condition); @@ -609,6 +621,33 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions, std::swap(select->ifTrue, select->ifFalse); } } + if (ExpressionAnalyzer::equal(select->ifTrue, select->ifFalse)) { + // sides are identical, fold + EffectAnalyzer value(getPassOptions(), select->ifTrue); + if (value.hasSideEffects()) { + // at best we don't need the condition, but need to execute the value + // twice. a block is larger than a select by 2 bytes, and + // we must drop one value, so 3, while we save the condition, + // so it's not clear this is worth it, TODO + } else { + // value has no side effects + EffectAnalyzer condition(getPassOptions(), select->condition); + if (!condition.hasSideEffects()) { + return select->ifTrue; + } else { + // the condition is last, so we need a new local, and it may be + // a bad idea to use a block like we do for an if. Do it only if we + // can reorder + if (!condition.invalidates(value)) { + Builder builder(*getModule()); + return builder.makeSequence( + builder.makeDrop(select->condition), + select->ifTrue + ); + } + } + } + } } else if (auto* br = curr->dynCast<Break>()) { if (br->condition) { br->condition = optimizeBoolean(br->condition); diff --git a/test/passes/O.bin.txt b/test/passes/O.bin.txt index 7b80e0211..4c64af9c6 100644 --- a/test/passes/O.bin.txt +++ b/test/passes/O.bin.txt @@ -43,14 +43,7 @@ ) ) (func $2 (type $0) (param $0 i64) (result i64) - (if - (i64.eq - (get_local $0) - (i64.const 0) - ) - (unreachable) - (unreachable) - ) + (unreachable) ) (func $3 (type $0) (param $0 i64) (result i64) (local $1 i64) diff --git a/test/passes/optimize-instructions.txt b/test/passes/optimize-instructions.txt index 03edc6e4c..2b33bd700 100644 --- a/test/passes/optimize-instructions.txt +++ b/test/passes/optimize-instructions.txt @@ -406,7 +406,7 @@ (if i32 (i32.const 1) (call $ne0) - (call $ne0) + (call $ne1) ) (nop) ) @@ -418,6 +418,9 @@ (nop) ) ) + (func $ne1 (type $2) (result i32) + (unreachable) + ) (func $load-off-2 (type $3) (param $0 i32) (result i32) (i32.store (i32.const 6) @@ -1882,4 +1885,81 @@ ) ) ) + (func $if-parallel (type $4) (param $0 i32) (param $1 i32) + (drop + (i32.add + (get_local $1) + (i32.const 1) + ) + ) + (drop + (block i32 + (drop + (tee_local $0 + (get_local $1) + ) + ) + (i32.add + (get_local $1) + (i32.const 1) + ) + ) + ) + ) + (func $select-parallel (type $4) (param $0 i32) (param $1 i32) + (drop + (i32.add + (get_local $1) + (i32.const 1) + ) + ) + (drop + (select + (tee_local $0 + (get_local $1) + ) + (tee_local $0 + (get_local $1) + ) + (get_local $0) + ) + ) + (drop + (block i32 + (drop + (tee_local $0 + (get_local $1) + ) + ) + (i32.add + (get_local $1) + (i32.const 1) + ) + ) + ) + (drop + (select + (tee_local $0 + (get_local $1) + ) + (tee_local $0 + (get_local $1) + ) + (tee_local $0 + (get_local $1) + ) + ) + ) + (drop + (select + (tee_local $0 + (get_local $1) + ) + (tee_local $0 + (get_local $1) + ) + (unreachable) + ) + ) + ) ) diff --git a/test/passes/optimize-instructions.wast b/test/passes/optimize-instructions.wast index eccbf1268..56defd648 100644 --- a/test/passes/optimize-instructions.wast +++ b/test/passes/optimize-instructions.wast @@ -319,7 +319,7 @@ (if i32 (i32.const 1) (i32.ne (call $ne0) (i32.const 0)) - (i32.ne (call $ne0) (i32.const 0)) + (i32.ne (call $ne1) (i32.const 0)) ) (nop) ) @@ -331,6 +331,9 @@ (nop) ) ) + (func $ne1 (result i32) + (unreachable) + ) (func $load-off-2 "load-off-2" (param $0 i32) (result i32) (i32.store offset=2 (i32.add @@ -2303,4 +2306,57 @@ ) ) ) + (func $if-parallel (param $0 i32) (param $1 i32) + (drop + (if i32 + (get_local $0) + (i32.add (get_local $1) (i32.const 1)) + (i32.add (get_local $1) (i32.const 1)) + ) + ) + (drop + (if i32 + (tee_local $0 (get_local $1)) ;; side effects! + (i32.add (get_local $1) (i32.const 1)) + (i32.add (get_local $1) (i32.const 1)) + ) + ) + ) + (func $select-parallel (param $0 i32) (param $1 i32) + (drop + (select + (i32.add (get_local $1) (i32.const 1)) + (i32.add (get_local $1) (i32.const 1)) + (get_local $0) + ) + ) + (drop + (select + (tee_local $0 (get_local $1)) ;; side effects! + (tee_local $0 (get_local $1)) ;; side effects! + (get_local $0) + ) + ) + (drop + (select + (i32.add (get_local $1) (i32.const 1)) + (i32.add (get_local $1) (i32.const 1)) + (tee_local $0 (get_local $1)) ;; side effects! (but no interference with values) + ) + ) + (drop + (select + (tee_local $0 (get_local $1)) ;; side effects! interference! + (tee_local $0 (get_local $1)) ;; side effects! interference! + (tee_local $0 (get_local $1)) ;; side effects! interference! + ) + ) + (drop + (select + (tee_local $0 (get_local $1)) ;; side effects! + (tee_local $0 (get_local $1)) ;; side effects! + (unreachable) ;; side effects! (but no interference with values) + ) + ) + ) ) diff --git a/test/wasm-only.fromasm b/test/wasm-only.fromasm index b8d876711..6fa30ba12 100644 --- a/test/wasm-only.fromasm +++ b/test/wasm-only.fromasm @@ -306,29 +306,14 @@ (i64.const 0) ) (func $ifValue64 (param $0 i64) (param $1 i64) (result i64) - (if i64 - (i32.wrap/i64 - (get_local $1) - ) - (call $call2 - (get_local $0) - ) - (call $call2 - (get_local $0) - ) + (call $call2 + (get_local $0) ) ) (func $ifValue32 (param $0 i32) (param $1 i32) (result i32) - (if i32 + (call $ifValue32 + (get_local $0) (get_local $1) - (call $ifValue32 - (get_local $0) - (get_local $1) - ) - (call $ifValue32 - (get_local $0) - (get_local $1) - ) ) ) (func $switch64 (param $0 i64) (result i32) diff --git a/test/wasm-only.fromasm.clamp b/test/wasm-only.fromasm.clamp index b8d876711..6fa30ba12 100644 --- a/test/wasm-only.fromasm.clamp +++ b/test/wasm-only.fromasm.clamp @@ -306,29 +306,14 @@ (i64.const 0) ) (func $ifValue64 (param $0 i64) (param $1 i64) (result i64) - (if i64 - (i32.wrap/i64 - (get_local $1) - ) - (call $call2 - (get_local $0) - ) - (call $call2 - (get_local $0) - ) + (call $call2 + (get_local $0) ) ) (func $ifValue32 (param $0 i32) (param $1 i32) (result i32) - (if i32 + (call $ifValue32 + (get_local $0) (get_local $1) - (call $ifValue32 - (get_local $0) - (get_local $1) - ) - (call $ifValue32 - (get_local $0) - (get_local $1) - ) ) ) (func $switch64 (param $0 i64) (result i32) diff --git a/test/wasm-only.fromasm.imprecise b/test/wasm-only.fromasm.imprecise index ae68d6a66..11eedc71d 100644 --- a/test/wasm-only.fromasm.imprecise +++ b/test/wasm-only.fromasm.imprecise @@ -221,29 +221,14 @@ (i64.const 0) ) (func $ifValue64 (param $0 i64) (param $1 i64) (result i64) - (if i64 - (i32.wrap/i64 - (get_local $1) - ) - (call $call2 - (get_local $0) - ) - (call $call2 - (get_local $0) - ) + (call $call2 + (get_local $0) ) ) (func $ifValue32 (param $0 i32) (param $1 i32) (result i32) - (if i32 + (call $ifValue32 + (get_local $0) (get_local $1) - (call $ifValue32 - (get_local $0) - (get_local $1) - ) - (call $ifValue32 - (get_local $0) - (get_local $1) - ) ) ) (func $switch64 (param $0 i64) (result i32) |