summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/Directize.cpp19
-rw-r--r--test/lit/passes/directize_all-features.wast55
2 files changed, 63 insertions, 11 deletions
diff --git a/src/passes/Directize.cpp b/src/passes/Directize.cpp
index ea6a946f5..b0236e32e 100644
--- a/src/passes/Directize.cpp
+++ b/src/passes/Directize.cpp
@@ -69,6 +69,11 @@ struct FunctionDirectizer : public WalkerPass<PostWalker<FunctionDirectizer>> {
auto* func = getFunction();
std::vector<Expression*> blockContents;
+ if (select->condition->type == Type::unreachable) {
+ // Leave this for DCE.
+ return;
+ }
+
// We must use the operands twice, and also must move the condition to
// execute first; use locals for them all. While doing so, if we see
// any are unreachable, stop trying to optimize and leave this for DCE.
@@ -78,13 +83,16 @@ struct FunctionDirectizer : public WalkerPass<PostWalker<FunctionDirectizer>> {
!TypeUpdating::canHandleAsLocal(operand->type)) {
return;
}
+ }
+
+ // None of the types are a problem, so we can proceed to add new vars as
+ // needed and perform this optimization.
+ for (auto* operand : curr->operands) {
auto currLocal = builder.addVar(func, operand->type);
operandLocals.push_back(currLocal);
blockContents.push_back(builder.makeLocalSet(currLocal, operand));
- }
-
- if (select->condition->type == Type::unreachable) {
- return;
+ // By adding locals we must make type adjustments at the end.
+ changedTypes = true;
}
// Build the calls.
@@ -106,9 +114,6 @@ struct FunctionDirectizer : public WalkerPass<PostWalker<FunctionDirectizer>> {
auto* iff = builder.makeIf(select->condition, ifTrueCall, ifFalseCall);
blockContents.push_back(iff);
replaceCurrent(builder.makeBlock(blockContents));
-
- // By adding locals we must make type adjustments at the end.
- changedTypes = true;
}
}
}
diff --git a/test/lit/passes/directize_all-features.wast b/test/lit/passes/directize_all-features.wast
index 9220b24e2..4c1400c54 100644
--- a/test/lit/passes/directize_all-features.wast
+++ b/test/lit/passes/directize_all-features.wast
@@ -728,8 +728,6 @@
)
)
;; CHECK: (func $select-unreachable-condition (param $x i32) (param $y i32) (param $z i32)
- ;; CHECK-NEXT: (local $3 i32)
- ;; CHECK-NEXT: (local $4 i32)
;; CHECK-NEXT: (call_indirect $0 (type $ii)
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: (local.get $y)
@@ -741,7 +739,8 @@
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $select-unreachable-condition (param $x i32) (param $y i32) (param $z i32)
- ;; The condition is unreachable.
+ ;; The condition is unreachable. We should not even create any vars here, and
+ ;; just not do anything.
(call_indirect (type $ii)
(local.get $x)
(local.get $y)
@@ -755,9 +754,11 @@
)
(module
+ ;; CHECK: (type $F (func (param (ref func))))
+
;; CHECK: (type $i32_=>_none (func (param i32)))
- ;; CHECK: (type $F (func (param (ref func))))
+ ;; CHECK: (type $none_=>_none (func))
;; CHECK: (table $0 15 15 funcref)
(table $0 15 15 funcref)
@@ -807,6 +808,52 @@
)
)
)
+
+ ;; CHECK: (func $select-non-nullable-unreachable-condition
+ ;; CHECK-NEXT: (call_indirect $0 (type $F)
+ ;; CHECK-NEXT: (ref.func $select-non-nullable)
+ ;; CHECK-NEXT: (select
+ ;; CHECK-NEXT: (i32.const 10)
+ ;; CHECK-NEXT: (i32.const 11)
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $select-non-nullable-unreachable-condition
+ ;; Test we ignore an unreachable condition and don't make any changes at all
+ ;; to the code (in particular, we shouldn't add any vars).
+ (call_indirect (type $F)
+ (ref.func $select-non-nullable)
+ (select
+ (i32.const 10)
+ (i32.const 11)
+ (unreachable)
+ )
+ )
+ )
+
+ ;; CHECK: (func $select-non-nullable-unreachable-arg (param $x i32)
+ ;; CHECK-NEXT: (call_indirect $0 (type $F)
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: (select
+ ;; CHECK-NEXT: (i32.const 10)
+ ;; CHECK-NEXT: (i32.const 11)
+ ;; CHECK-NEXT: (local.get $x)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $select-non-nullable-unreachable-arg (param $x i32)
+ ;; Test we ignore an unreachable argument and don't make any changes at all
+ ;; to the code (in particular, we shouldn't add any vars).
+ (call_indirect (type $F)
+ (unreachable)
+ (select
+ (i32.const 10)
+ (i32.const 11)
+ (local.get $x)
+ )
+ )
+ )
)
;; A table.set prevents optimization.