summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/OptimizeInstructions.cpp29
-rw-r--r--test/passes/optimize-instructions.txt34
-rw-r--r--test/passes/optimize-instructions.wast21
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