diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h index 3561a40bad6..4d60423ef49 100644 --- a/src/wasm-ir-builder.h +++ b/src/wasm-ir-builder.h @@ -511,6 +511,10 @@ class IRBuilder : public UnifiedExpressionVisitor> { } } bool isNone() { return std::get_if(&scope); } + bool isInputLocal(Index local) const { + return std::find(inputLocals.begin(), inputLocals.end(), local) != + inputLocals.end(); + } Function* getFunction() { if (auto* funcScope = std::get_if(&scope)) { return funcScope->func; diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp index 9799b8861f6..1687c4a56c8 100644 --- a/src/wasm/wasm-ir-builder.cpp +++ b/src/wasm/wasm-ir-builder.cpp @@ -138,6 +138,15 @@ MaybeResult IRBuilder::hoistLastValue(bool greedy) { // No need for a scratch local to hoist an unreachable. return HoistedVal{Index(hoistIndex), nullptr}; } + if (auto* get = expr->dynCast(); + get && getScope().isInputLocal(get->index)) { + // Input scratch locals are never modified while their initial `local.get`s + // remain on the stack, so we can hoist them directly across subsequent + // none-typed expressions without allocating a new scratch local. + stack.erase(stack.begin() + valIndex); + stack.push_back(get); + return HoistedVal{Index(stack.size() - 1), nullptr}; + } // Hoist with a scratch local. Normally the scratch local is the same type as // the hoisted expression, but we may need to adjust it given the enabled // features. Otherwise, if the expression has a tuple type with a more refined @@ -919,24 +928,17 @@ Result<> IRBuilder::pushScope(ScopeCtx&& scope) { inputs.push_back(getScope().exprStack.back()); getScope().exprStack.pop_back(); } - const auto& parentLocals = getScope().inputLocals; - // The new scope may only receive a suffix of the outer scope's parameters, - // so match inputs starting from the remaining size of the outer stack - // rather than from the beginning. - size_t baseIndex = getScope().exprStack.size(); for (size_t i = 0; i < inputs.size(); ++i) { // Move an enclosing scope's input expression (a scratch local.get or a // catch pop) directly into this scope rather than allocating a new // scratch local. auto* expr = inputs[i]; - size_t parentIndex = baseIndex + i; - bool isInputGet = expr->is() && - expr->type == scope.inputType[i] && - parentIndex < parentLocals.size(); + auto* get = expr->dynCast(); + bool isInputGet = get && get->type == scope.inputType[i] && + getScope().isInputLocal(get->index); bool isPop = isUnnamedBlock && inputs.size() == 1 && expr->is(); if (isInputGet) { - assert(expr->cast()->index == parentLocals[parentIndex]); - scope.inputLocals.push_back(parentLocals[parentIndex]); + scope.inputLocals.push_back(get->index); } else if (!isPop) { auto scratch = addScratchLocal(scope.inputType[i]); CHECK_ERR(scratch); diff --git a/test/lit/basic/extra-branch-values.wast b/test/lit/basic/extra-branch-values.wast index 8f0980c6b9a..d54b880fbfc 100644 --- a/test/lit/basic/extra-branch-values.wast +++ b/test/lit/basic/extra-branch-values.wast @@ -1844,41 +1844,35 @@ ;; CHECK-NEXT: (local $scratch i64) ;; CHECK-NEXT: (local $scratch_3 anyref) ;; CHECK-NEXT: (local $scratch_4 i64) - ;; CHECK-NEXT: (local $scratch_5 i64) - ;; CHECK-NEXT: (local $scratch_6 (ref any)) - ;; CHECK-NEXT: (local $scratch_7 i64) - ;; CHECK-NEXT: (local $scratch_8 eqref) + ;; CHECK-NEXT: (local $scratch_5 (ref any)) + ;; CHECK-NEXT: (local $scratch_6 i64) + ;; CHECK-NEXT: (local $scratch_7 eqref) ;; CHECK-NEXT: (local.set $scratch ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block $block (type $12) (result i64 eqref) - ;; CHECK-NEXT: (local.set $scratch_8 + ;; CHECK-NEXT: (local.set $scratch_7 ;; CHECK-NEXT: (block $block0 (result eqref) + ;; CHECK-NEXT: (local.set $scratch_3 + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $scratch_4 - ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $scratch_5 - ;; CHECK-NEXT: (local.get $scratch) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $scratch_3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $scratch_5) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $scratch_6 + ;; CHECK-NEXT: (local.set $scratch_5 ;; CHECK-NEXT: (br_on_cast $block0 anyref eqref ;; CHECK-NEXT: (local.get $scratch_3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (global.set $i64 ;; CHECK-NEXT: (block (result i64) - ;; CHECK-NEXT: (local.set $scratch_7 + ;; CHECK-NEXT: (local.set $scratch_6 ;; CHECK-NEXT: (local.get $scratch_4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (global.set $any - ;; CHECK-NEXT: (local.get $scratch_6) + ;; CHECK-NEXT: (local.get $scratch_5) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $scratch_7) + ;; CHECK-NEXT: (local.get $scratch_6) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $block @@ -1891,7 +1885,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (tuple.make 2 ;; CHECK-NEXT: (local.get $scratch_4) - ;; CHECK-NEXT: (local.get $scratch_8) + ;; CHECK-NEXT: (local.get $scratch_7) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1935,11 +1929,10 @@ ;; CHECK-NEXT: (local $scratch_3 anyref) ;; CHECK-NEXT: (local $scratch_4 anyref) ;; CHECK-NEXT: (local $scratch_5 i32) - ;; CHECK-NEXT: (local $scratch_6 i32) - ;; CHECK-NEXT: (local $scratch_7 (ref any)) - ;; CHECK-NEXT: (local $scratch_8 i32) - ;; CHECK-NEXT: (local $scratch_9 anyref) - ;; CHECK-NEXT: (local $scratch_10 (tuple i32 anyref)) + ;; CHECK-NEXT: (local $scratch_6 (ref any)) + ;; CHECK-NEXT: (local $scratch_7 i32) + ;; CHECK-NEXT: (local $scratch_8 anyref) + ;; CHECK-NEXT: (local $scratch_9 (tuple i32 anyref)) ;; CHECK-NEXT: (local.set $scratch ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -1948,36 +1941,31 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $label2 ;; CHECK-NEXT: (block $label3 - ;; CHECK-NEXT: (local.set $scratch_10 + ;; CHECK-NEXT: (local.set $scratch_9 ;; CHECK-NEXT: (block $label (type $2) (result i32 anyref) ;; CHECK-NEXT: (block $label1 - ;; CHECK-NEXT: (local.set $scratch_9 + ;; CHECK-NEXT: (local.set $scratch_8 ;; CHECK-NEXT: (block $label0 (result anyref) + ;; CHECK-NEXT: (local.set $scratch_4 + ;; CHECK-NEXT: (local.get $scratch_3) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $scratch_5 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_6 - ;; CHECK-NEXT: (local.get $scratch) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $scratch_4 - ;; CHECK-NEXT: (local.get $scratch_3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $scratch_6) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $scratch_7 + ;; CHECK-NEXT: (local.set $scratch_6 ;; CHECK-NEXT: (br_on_cast $label0 anyref eqref ;; CHECK-NEXT: (local.get $scratch_4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (global.set $i32 ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_8 + ;; CHECK-NEXT: (local.set $scratch_7 ;; CHECK-NEXT: (local.get $scratch_5) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (global.set $any - ;; CHECK-NEXT: (local.get $scratch_7) + ;; CHECK-NEXT: (local.get $scratch_6) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $scratch_8) + ;; CHECK-NEXT: (local.get $scratch_7) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $label1) @@ -1986,7 +1974,7 @@ ;; CHECK-NEXT: (br $label ;; CHECK-NEXT: (tuple.make 2 ;; CHECK-NEXT: (local.get $scratch_5) - ;; CHECK-NEXT: (local.get $scratch_9) + ;; CHECK-NEXT: (local.get $scratch_8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1995,12 +1983,12 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $scratch ;; CHECK-NEXT: (tuple.extract 2 0 - ;; CHECK-NEXT: (local.get $scratch_10) + ;; CHECK-NEXT: (local.get $scratch_9) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $scratch_3 ;; CHECK-NEXT: (tuple.extract 2 1 - ;; CHECK-NEXT: (local.get $scratch_10) + ;; CHECK-NEXT: (local.get $scratch_9) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $label2) @@ -2042,10 +2030,9 @@ ;; CHECK-NEXT: (local $scratch_3 anyref) ;; CHECK-NEXT: (local $scratch_4 anyref) ;; CHECK-NEXT: (local $scratch_5 i32) - ;; CHECK-NEXT: (local $scratch_6 i32) - ;; CHECK-NEXT: (local $scratch_7 (ref any)) - ;; CHECK-NEXT: (local $scratch_8 anyref) - ;; CHECK-NEXT: (local $scratch_9 (tuple i32 anyref)) + ;; CHECK-NEXT: (local $scratch_6 (ref any)) + ;; CHECK-NEXT: (local $scratch_7 anyref) + ;; CHECK-NEXT: (local $scratch_8 (tuple i32 anyref)) ;; CHECK-NEXT: (local.set $scratch ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -2054,24 +2041,19 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $label2 (type $2) (result i32 anyref) ;; CHECK-NEXT: (block $label3 (type $2) (result i32 anyref) - ;; CHECK-NEXT: (local.set $scratch_9 + ;; CHECK-NEXT: (local.set $scratch_8 ;; CHECK-NEXT: (block $label (type $2) (result i32 anyref) ;; CHECK-NEXT: (br $label3 ;; CHECK-NEXT: (block $label1 (type $2) (result i32 anyref) - ;; CHECK-NEXT: (local.set $scratch_8 + ;; CHECK-NEXT: (local.set $scratch_7 ;; CHECK-NEXT: (block $label0 (result anyref) + ;; CHECK-NEXT: (local.set $scratch_4 + ;; CHECK-NEXT: (local.get $scratch_3) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $scratch_5 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_6 - ;; CHECK-NEXT: (local.get $scratch) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $scratch_4 - ;; CHECK-NEXT: (local.get $scratch_3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $scratch_6) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $scratch_7 + ;; CHECK-NEXT: (local.set $scratch_6 ;; CHECK-NEXT: (br_on_cast $label0 anyref eqref ;; CHECK-NEXT: (local.get $scratch_4) ;; CHECK-NEXT: ) @@ -2079,7 +2061,7 @@ ;; CHECK-NEXT: (br $label1 ;; CHECK-NEXT: (tuple.make 2 ;; CHECK-NEXT: (local.get $scratch_5) - ;; CHECK-NEXT: (local.get $scratch_7) + ;; CHECK-NEXT: (local.get $scratch_6) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2087,7 +2069,7 @@ ;; CHECK-NEXT: (br $label ;; CHECK-NEXT: (tuple.make 2 ;; CHECK-NEXT: (local.get $scratch_5) - ;; CHECK-NEXT: (local.get $scratch_8) + ;; CHECK-NEXT: (local.get $scratch_7) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2096,12 +2078,12 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $scratch ;; CHECK-NEXT: (tuple.extract 2 0 - ;; CHECK-NEXT: (local.get $scratch_9) + ;; CHECK-NEXT: (local.get $scratch_8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $scratch_3 ;; CHECK-NEXT: (tuple.extract 2 1 - ;; CHECK-NEXT: (local.get $scratch_9) + ;; CHECK-NEXT: (local.get $scratch_8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $label2) @@ -2384,34 +2366,27 @@ ;; CHECK-NEXT: (local $scratch i32) ;; CHECK-NEXT: (local $scratch_5 anyref) ;; CHECK-NEXT: (local $scratch_6 i32) - ;; CHECK-NEXT: (local $scratch_7 i32) - ;; CHECK-NEXT: (local $scratch_8 (ref any)) - ;; CHECK-NEXT: (local $scratch_9 anyref) - ;; CHECK-NEXT: (local $scratch_10 i32) - ;; CHECK-NEXT: (local $scratch_11 (ref any)) - ;; CHECK-NEXT: (local $scratch_12 eqref) + ;; CHECK-NEXT: (local $scratch_7 (ref any)) + ;; CHECK-NEXT: (local $scratch_8 anyref) + ;; CHECK-NEXT: (local $scratch_9 (ref any)) + ;; CHECK-NEXT: (local $scratch_10 eqref) ;; CHECK-NEXT: (local.set $scratch ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block $label (type $0) (result i32 eqref) - ;; CHECK-NEXT: (local.set $scratch_12 + ;; CHECK-NEXT: (local.set $scratch_10 ;; CHECK-NEXT: (block $label0 (result eqref) ;; CHECK-NEXT: (br $label ;; CHECK-NEXT: (if (type $0) (result i32 eqref) ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $scratch_5 + ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $scratch_6 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_7 - ;; CHECK-NEXT: (local.get $scratch) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $scratch_5 - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $scratch_7) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $scratch_8 + ;; CHECK-NEXT: (local.set $scratch_7 ;; CHECK-NEXT: (br_on_cast $label0 anyref eqref ;; CHECK-NEXT: (local.get $scratch_5) ;; CHECK-NEXT: ) @@ -2420,34 +2395,29 @@ ;; CHECK-NEXT: (local.get $scratch_6) ;; CHECK-NEXT: (block (result (ref eq)) ;; CHECK-NEXT: (global.set $any - ;; CHECK-NEXT: (local.get $scratch_8) + ;; CHECK-NEXT: (local.get $scratch_7) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (global.get $eq) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $scratch_8 + ;; CHECK-NEXT: (local.get $3) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $scratch_6 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_10 - ;; CHECK-NEXT: (local.get $scratch) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $scratch_9 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $scratch_10) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $scratch_11 + ;; CHECK-NEXT: (local.set $scratch_9 ;; CHECK-NEXT: (br_on_cast $label0 anyref eqref - ;; CHECK-NEXT: (local.get $scratch_9) + ;; CHECK-NEXT: (local.get $scratch_8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (tuple.make 2 ;; CHECK-NEXT: (local.get $scratch_6) ;; CHECK-NEXT: (block (result eqref) ;; CHECK-NEXT: (global.set $any - ;; CHECK-NEXT: (local.get $scratch_11) + ;; CHECK-NEXT: (local.get $scratch_9) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (global.get $eqref) ;; CHECK-NEXT: ) @@ -2459,7 +2429,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (tuple.make 2 ;; CHECK-NEXT: (local.get $scratch_6) - ;; CHECK-NEXT: (local.get $scratch_12) + ;; CHECK-NEXT: (local.get $scratch_10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -2799,37 +2769,31 @@ ;; CHECK-NEXT: (local $scratch i32) ;; CHECK-NEXT: (local $scratch_3 anyref) ;; CHECK-NEXT: (local $scratch_4 i32) - ;; CHECK-NEXT: (local $scratch_5 i32) - ;; CHECK-NEXT: (local $scratch_6 (ref any)) - ;; CHECK-NEXT: (local $scratch_7 eqref) + ;; CHECK-NEXT: (local $scratch_5 (ref any)) + ;; CHECK-NEXT: (local $scratch_6 eqref) ;; CHECK-NEXT: (local.set $scratch ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block $label (type $0) (result i32 eqref) - ;; CHECK-NEXT: (local.set $scratch_7 + ;; CHECK-NEXT: (local.set $scratch_6 ;; CHECK-NEXT: (block $label0 (result eqref) ;; CHECK-NEXT: (br $label ;; CHECK-NEXT: (try (type $0) (result i32 eqref) ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (local.set $scratch_3 + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $scratch_4 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_5 - ;; CHECK-NEXT: (local.get $scratch) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $scratch_3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $scratch_5) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $scratch_6 + ;; CHECK-NEXT: (local.set $scratch_5 ;; CHECK-NEXT: (br_on_cast $label0 anyref eqref ;; CHECK-NEXT: (local.get $scratch_3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $use-i32-any ;; CHECK-NEXT: (local.get $scratch_4) - ;; CHECK-NEXT: (local.get $scratch_6) + ;; CHECK-NEXT: (local.get $scratch_5) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (tuple.make 2 ;; CHECK-NEXT: (i32.const 0) @@ -2860,7 +2824,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (tuple.make 2 ;; CHECK-NEXT: (local.get $scratch_4) - ;; CHECK-NEXT: (local.get $scratch_7) + ;; CHECK-NEXT: (local.get $scratch_6) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -3008,36 +2972,30 @@ ;; CHECK-NEXT: (local $scratch i32) ;; CHECK-NEXT: (local $scratch_3 anyref) ;; CHECK-NEXT: (local $scratch_4 i32) - ;; CHECK-NEXT: (local $scratch_5 i32) - ;; CHECK-NEXT: (local $scratch_6 (ref any)) - ;; CHECK-NEXT: (local $scratch_7 eqref) + ;; CHECK-NEXT: (local $scratch_5 (ref any)) + ;; CHECK-NEXT: (local $scratch_6 eqref) ;; CHECK-NEXT: (local.set $scratch ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block $label (type $0) (result i32 eqref) - ;; CHECK-NEXT: (local.set $scratch_7 + ;; CHECK-NEXT: (local.set $scratch_6 ;; CHECK-NEXT: (block $label0 (result eqref) ;; CHECK-NEXT: (br $label ;; CHECK-NEXT: (try_table (type $0) (result i32 eqref) + ;; CHECK-NEXT: (local.set $scratch_3 + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $scratch_4 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_5 - ;; CHECK-NEXT: (local.get $scratch) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $scratch_3 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $scratch_5) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $scratch_6 + ;; CHECK-NEXT: (local.set $scratch_5 ;; CHECK-NEXT: (br_on_cast $label0 anyref eqref ;; CHECK-NEXT: (local.get $scratch_3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $use-i32-any ;; CHECK-NEXT: (local.get $scratch_4) - ;; CHECK-NEXT: (local.get $scratch_6) + ;; CHECK-NEXT: (local.get $scratch_5) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (tuple.make 2 ;; CHECK-NEXT: (i32.const 0) @@ -3049,7 +3007,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (tuple.make 2 ;; CHECK-NEXT: (local.get $scratch_4) - ;; CHECK-NEXT: (local.get $scratch_7) + ;; CHECK-NEXT: (local.get $scratch_6) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) diff --git a/test/lit/basic/pop-fixup.wast b/test/lit/basic/pop-fixup.wast index 2be69ae28d3..59621044f49 100644 --- a/test/lit/basic/pop-fixup.wast +++ b/test/lit/basic/pop-fixup.wast @@ -289,8 +289,6 @@ ;; CHECK-NEXT: (local $scratch (tuple i32 i32)) ;; CHECK-NEXT: (local $scratch_1 i32) ;; CHECK-NEXT: (local $scratch_2 i32) - ;; CHECK-NEXT: (local $scratch_3 i32) - ;; CHECK-NEXT: (local $scratch_4 i32) ;; CHECK-NEXT: (try ;; CHECK-NEXT: (do ;; CHECK-NEXT: ) @@ -308,22 +306,12 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_4 - ;; CHECK-NEXT: (local.get $scratch_1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_3 - ;; CHECK-NEXT: (local.get $scratch_2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.get $scratch_3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $scratch_4) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch_2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $scratch_1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -334,7 +322,8 @@ catch $e2 ;; An unnamed block with multivalue input params extracts the tuple elements ;; into scratch locals before the block rather than moving the pop into the - ;; block. + ;; block. Inside the block, the input local.gets are hoisted across the nop + ;; without needing extra scratch locals. block (param i32 i32) nop drop diff --git a/test/lit/control-flow-input.wast b/test/lit/control-flow-input.wast index 6992e7021eb..3cef2981a5e 100644 --- a/test/lit/control-flow-input.wast +++ b/test/lit/control-flow-input.wast @@ -186,7 +186,6 @@ ;; CHECK: (func $block-multivalue-drop (type $2) ;; CHECK-NEXT: (local $scratch i32) ;; CHECK-NEXT: (local $scratch_1 i64) - ;; CHECK-NEXT: (local $scratch_2 i32) ;; CHECK-NEXT: (local.set $scratch ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) @@ -195,15 +194,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_2 - ;; CHECK-NEXT: (local.get $scratch) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $scratch_1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $scratch_2) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch_1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $scratch) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -218,16 +212,12 @@ ;; CHECK: (func $block-passthrough-nop (type $1) (result i32) ;; CHECK-NEXT: (local $scratch i32) - ;; CHECK-NEXT: (local $scratch_1 i32) ;; CHECK-NEXT: (local.set $scratch ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_1 - ;; CHECK-NEXT: (local.get $scratch) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.get $scratch_1) + ;; CHECK-NEXT: (local.get $scratch) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $block-passthrough-nop (result i32) @@ -769,8 +759,6 @@ ;; CHECK: (func $if-else-multivalue (type $8) (result f32) ;; CHECK-NEXT: (local $scratch i32) ;; CHECK-NEXT: (local $scratch_1 i64) - ;; CHECK-NEXT: (local $scratch_2 i32) - ;; CHECK-NEXT: (local $scratch_3 i32) ;; CHECK-NEXT: (local.set $scratch ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) @@ -781,29 +769,19 @@ ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_2 - ;; CHECK-NEXT: (local.get $scratch) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $scratch_1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $scratch_2) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch_1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $scratch) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (f32.const 3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_3 - ;; CHECK-NEXT: (local.get $scratch) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $scratch_1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $scratch_3) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $scratch_1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $scratch) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (f32.const 4) ;; CHECK-NEXT: ) @@ -864,35 +842,25 @@ ;; CHECK: (func $if-tunnel-nop (type $1) (result i32) ;; CHECK-NEXT: (local $scratch i32) - ;; CHECK-NEXT: (local $scratch_1 i32) - ;; CHECK-NEXT: (local $scratch_2 i32) ;; CHECK-NEXT: (local.set $scratch ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_2 - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $scratch_1 - ;; CHECK-NEXT: (local.get $scratch) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (local.get $scratch_1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: (if (result i32) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.get $scratch_2) + ;; CHECK-NEXT: (local.get $scratch) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.get $scratch_2) + ;; CHECK-NEXT: (local.get $scratch) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $if-tunnel-nop (result i32) - ;; A none-typed instruction before an if wraps the outer input in a block - ;; when popping the if input, requiring a new scratch local for the if. + ;; A none-typed instruction before an if does not prevent the outer input + ;; from being hoisted and tunneled into the if. i32.const 0 block (param i32) (result i32) nop