summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/OptimizeInstructions.cpp39
-rw-r--r--test/passes/O.bin.txt9
-rw-r--r--test/passes/optimize-instructions.txt82
-rw-r--r--test/passes/optimize-instructions.wast58
-rw-r--r--test/wasm-only.fromasm23
-rw-r--r--test/wasm-only.fromasm.clamp23
-rw-r--r--test/wasm-only.fromasm.imprecise23
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)