diff options
-rw-r--r-- | src/passes/Directize.cpp | 19 | ||||
-rw-r--r-- | test/lit/passes/directize_all-features.wast | 55 |
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. |