From 83af22c9938e7b8f6dbb8b181a40c586436cbd96 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 08:43:02 -0700 Subject: [PATCH 01/77] work --- src/passes/CMakeLists.txt | 1 - src/passes/StackIR.cpp | 505 ----------------------------------- src/passes/passes.h | 3 - src/wasm-stack.h | 27 ++ src/wasm/CMakeLists.txt | 1 + src/wasm/wasm-binary.cpp | 13 + src/wasm/wasm-stack-opts.cpp | 450 +++++++++++++++++++++++++++++++ 7 files changed, 491 insertions(+), 509 deletions(-) delete mode 100644 src/passes/StackIR.cpp create mode 100644 src/wasm/wasm-stack-opts.cpp diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt index 1e5540ab047..72fa02b62e4 100644 --- a/src/passes/CMakeLists.txt +++ b/src/passes/CMakeLists.txt @@ -87,7 +87,6 @@ set(passes_SOURCES PrintFunctionMap.cpp RoundTrip.cpp SetGlobals.cpp - StackIR.cpp SignaturePruning.cpp SignatureRefining.cpp SignExtLowering.cpp diff --git a/src/passes/StackIR.cpp b/src/passes/StackIR.cpp deleted file mode 100644 index 24b4fcbe844..00000000000 --- a/src/passes/StackIR.cpp +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright 2018 WebAssembly Community Group participants - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Operations on Stack IR. -// - -#include "ir/iteration.h" -#include "ir/local-graph.h" -#include "pass.h" -#include "wasm-stack.h" -#include "wasm.h" - -namespace wasm { - -// Generate Stack IR from Binaryen IR - -struct GenerateStackIR : public WalkerPass> { - bool isFunctionParallel() override { return true; } - - std::unique_ptr create() override { - return std::make_unique(); - } - - bool modifiesBinaryenIR() override { return false; } - - void doWalkFunction(Function* func) { - StackIRGenerator stackIRGen(*getModule(), func); - stackIRGen.write(); - func->stackIR = std::make_unique(); - func->stackIR->swap(stackIRGen.getStackIR()); - } -}; - -Pass* createGenerateStackIRPass() { return new GenerateStackIR(); } - -// Optimize - -class StackIROptimizer { - Function* func; - PassOptions& passOptions; - StackIR& insts; - FeatureSet features; - -public: - StackIROptimizer(Function* func, - PassOptions& passOptions, - FeatureSet features) - : func(func), passOptions(passOptions), insts(*func->stackIR.get()), - features(features) { - assert(func->stackIR); - } - - void run() { - dce(); - // FIXME: local2Stack is currently rather slow (due to localGraph), - // so for now run it only when really optimizing - if (passOptions.optimizeLevel >= 3 || passOptions.shrinkLevel >= 1) { - local2Stack(); - } - removeUnneededBlocks(); - dce(); - vacuum(); - } - -private: - // Passes. - - // Remove unreachable code. - void dce() { - bool inUnreachableCode = false; - for (Index i = 0; i < insts.size(); i++) { - auto* inst = insts[i]; - if (!inst) { - continue; - } - if (inUnreachableCode) { - // Does the unreachable code end here? - if (isControlFlowBarrier(inst)) { - inUnreachableCode = false; - } else { - // We can remove this. - removeAt(i); - } - } else if (inst->type == Type::unreachable) { - inUnreachableCode = true; - } - } - } - - // Remove obviously-unneeded code. - void vacuum() { - // In the wasm binary format a nop is never needed. (In Binaryen IR, in - // comparison, it is necessary e.g. in a function body or an if arm.) - // - // It is especially important to remove nops because we add nops when we - // read wasm into Binaryen IR. That is, this avoids a potential increase in - // code size. - for (Index i = 0; i < insts.size(); i++) { - auto*& inst = insts[i]; - if (inst && inst->origin->is()) { - inst = nullptr; - } - } - } - - // If ordered properly, we can avoid a local.set/local.get pair, - // and use the value directly from the stack, for example - // [..produce a value on the stack..] - // local.set $x - // [..much code..] - // local.get $x - // call $foo ;; use the value, foo(value) - // As long as the code in between does not modify $x, and has - // no control flow branching out, we can remove both the set - // and the get. - void local2Stack() { - // We use the localGraph to tell us if a get-set pair is indeed - // a set that is read by that get, and only that get. Note that we run - // this on the Binaryen IR, so we are assuming that no previous opt - // has changed the interaction of local operations. - // TODO: we can do this a lot faster, as we just care about linear - // control flow. - LocalGraph localGraph(func); - localGraph.computeSetInfluences(); - // We maintain a stack of relevant values. This contains: - // * a null for each actual value that the value stack would have - // * an index of each LocalSet that *could* be on the value - // stack at that location. - const Index null = -1; - std::vector values; - // We also maintain a stack of values vectors for control flow, - // saving the stack as we enter and restoring it when we exit. - std::vector> savedValues; -#ifdef STACK_OPT_DEBUG - std::cout << "func: " << func->name << '\n' << insts << '\n'; -#endif - for (Index instIndex = 0; instIndex < insts.size(); instIndex++) { - auto* inst = insts[instIndex]; - if (!inst) { - continue; - } - // First, consume values from the stack as required. - auto consumed = getNumConsumedValues(inst); -#ifdef STACK_OPT_DEBUG - std::cout << " " << instIndex << " : " << *inst << ", " << values.size() - << " on stack, will consume " << consumed << "\n "; - for (auto s : values) - std::cout << s << ' '; - std::cout << '\n'; -#endif - // TODO: currently we run dce before this, but if we didn't, we'd need - // to handle unreachable code here - it's ok to pop multiple values - // there even if the stack is at size 0. - while (consumed > 0) { - assert(values.size() > 0); - // Whenever we hit a possible stack value, kill it - it would - // be consumed here, so we can never optimize to it. - while (values.back() != null) { - values.pop_back(); - assert(values.size() > 0); - } - // Finally, consume the actual value that is consumed here. - values.pop_back(); - consumed--; - } - // After consuming, we can see what to do with this. First, handle - // control flow. - if (isControlFlowBegin(inst)) { - // Save the stack for when we end this control flow. - savedValues.push_back(values); // TODO: optimize copies - values.clear(); - } else if (isControlFlowEnd(inst)) { - assert(!savedValues.empty()); - values = savedValues.back(); - savedValues.pop_back(); - } else if (isControlFlow(inst)) { - // Otherwise, in the middle of control flow, just clear it - values.clear(); - } - // This is something we should handle, look into it. - if (inst->type.isConcrete()) { - bool optimized = false; - // Do not optimize multivalue locals, since those will be better - // optimized when they are visited in the binary writer and this - // optimization would intefere with that one. - if (auto* get = inst->origin->dynCast(); - get && inst->type.isSingle()) { - // Use another local to clarify what instIndex means in this scope. - auto getIndex = instIndex; - - // This is a potential optimization opportunity! See if we - // can reach the set. - if (values.size() > 0) { - Index j = values.size() - 1; - while (1) { - // If there's an actual value in the way, we've failed. - auto setIndex = values[j]; - if (setIndex == null) { - break; - } - auto* set = insts[setIndex]->origin->cast(); - if (set->index == get->index) { - // This might be a proper set-get pair, where the set is - // used by this get and nothing else, check that. - auto& sets = localGraph.getSetses[get]; - if (sets.size() == 1 && *sets.begin() == set) { - auto& setInfluences = localGraph.setInfluences[set]; - // If this has the proper value of 1, also do the potentially- - // expensive check of whether we can remove this pair at all. - if (setInfluences.size() == 1 && - canRemoveSetGetPair(setIndex, getIndex)) { - assert(*setInfluences.begin() == get); - // Do it! The set and the get can go away, the proper - // value is on the stack. -#ifdef STACK_OPT_DEBUG - std::cout << " stackify the get\n"; -#endif - insts[setIndex] = nullptr; - insts[getIndex] = nullptr; - // Continuing on from here, replace this on the stack - // with a null, representing a regular value. We - // keep possible values above us active - they may - // be optimized later, as they would be pushed after - // us, and used before us, so there is no conflict. - values[j] = null; - optimized = true; - break; - } - } - } - // We failed here. Can we look some more? - if (j == 0) { - break; - } - j--; - } - } - } - if (!optimized) { - // This is an actual regular value on the value stack. - values.push_back(null); - } - } else if (inst->origin->is() && inst->type == Type::none) { - // This set is potentially optimizable later, add to stack. - values.push_back(instIndex); - } - } - } - - // There may be unnecessary blocks we can remove: blocks - // without branches to them are always ok to remove. - // TODO: a branch to a block in an if body can become - // a branch to that if body - void removeUnneededBlocks() { - for (auto*& inst : insts) { - if (!inst) { - continue; - } - if (auto* block = inst->origin->dynCast()) { - if (!BranchUtils::BranchSeeker::has(block, block->name)) { - // TODO optimize, maybe run remove-unused-names - inst = nullptr; - } - } - } - } - - // Utilities. - - // A control flow "barrier" - a point where stack machine - // unreachability ends. - bool isControlFlowBarrier(StackInst* inst) { - switch (inst->op) { - case StackInst::BlockEnd: - case StackInst::IfElse: - case StackInst::IfEnd: - case StackInst::LoopEnd: - case StackInst::Catch: - case StackInst::CatchAll: - case StackInst::Delegate: - case StackInst::TryEnd: - case StackInst::TryTableEnd: { - return true; - } - default: { return false; } - } - } - - // A control flow beginning. - bool isControlFlowBegin(StackInst* inst) { - switch (inst->op) { - case StackInst::BlockBegin: - case StackInst::IfBegin: - case StackInst::LoopBegin: - case StackInst::TryBegin: - case StackInst::TryTableBegin: { - return true; - } - default: { return false; } - } - } - - // A control flow ending. - bool isControlFlowEnd(StackInst* inst) { - switch (inst->op) { - case StackInst::BlockEnd: - case StackInst::IfEnd: - case StackInst::LoopEnd: - case StackInst::TryEnd: - case StackInst::Delegate: - case StackInst::TryTableEnd: { - return true; - } - default: { return false; } - } - } - - bool isControlFlow(StackInst* inst) { return inst->op != StackInst::Basic; } - - // Remove the instruction at index i. If the instruction - // is control flow, and so has been expanded to multiple - // instructions, remove them as well. - void removeAt(Index i) { - auto* inst = insts[i]; - insts[i] = nullptr; - if (inst->op == StackInst::Basic) { - return; // that was it - } - auto* origin = inst->origin; - while (1) { - i++; - assert(i < insts.size()); - inst = insts[i]; - insts[i] = nullptr; - if (inst && inst->origin == origin && isControlFlowEnd(inst)) { - return; // that's it, we removed it all - } - } - } - - Index getNumConsumedValues(StackInst* inst) { - if (isControlFlow(inst)) { - // If consumes 1; that's it. - if (inst->op == StackInst::IfBegin) { - return 1; - } - return 0; - } - // Otherwise, for basic instructions, just count the expression children. - return ChildIterator(inst->origin).children.size(); - } - - // Given a pair of a local.set and local.get, see if we can remove them - // without breaking validation. Specifically, we must keep sets of non- - // nullable locals that dominate a get until the end of the block, such as - // here: - // - // local.set 0 ;; Can we remove - // local.get 0 ;; this pair? - // if - // local.set 0 - // else - // local.set 0 - // end - // local.get 0 ;; This get poses a problem. - // - // Logically the 2nd&3rd sets ensure a value is applied to the local before we - // read it, but the validation rules only track each set until the end of its - // scope, so the 1st set (before the if, in the pair) is necessary. - // - // The logic below is related to LocalStructuralDominance, but sharing code - // with it is difficult as this uses StackIR and not BinaryenIR, and it checks - // a particular set/get pair. - // - // We are given the indexes of the set and get instructions in |insts|. - bool canRemoveSetGetPair(Index setIndex, Index getIndex) { - // The set must be before the get. - assert(setIndex < getIndex); - - auto* set = insts[setIndex]->origin->cast(); - auto localType = func->getLocalType(set->index); - // Note we do not need to handle tuples here, as the parent ignores them - // anyhow (hence we can check non-nullability instead of non- - // defaultability). - assert(localType.isSingle()); - if (func->isParam(set->index) || !localType.isNonNullable()) { - // This local cannot pose a problem for validation (params are always - // initialized, and it is ok if nullable locals are uninitialized). - return true; - } - - // Track the depth (in block/if/loop/etc. scopes) relative to our starting - // point. Anything less deep than that is not interesting, as we can only - // help things at our depth or deeper to validate. - Index currDepth = 0; - - // Look for a different get than the one in getIndex (since that one is - // being removed) which would stop validating without the set. While doing - // so, note other sets that ensure validation even if our set is removed. We - // track those in this stack of booleans, one for each scope, which is true - // if another sets covers us and ours is not needed. - // - // We begin in the current scope and with no other set covering us. - std::vector coverStack = {false}; - - // Track the total number of covers as well, for quick checking below. - Index covers = 0; - - // TODO: We could look before us as well, but then we might end up scanning - // much of the function every time. - for (Index i = setIndex + 1; i < insts.size(); i++) { - auto* inst = insts[i]; - if (!inst) { - continue; - } - if (isControlFlowBegin(inst)) { - // A new scope begins. - currDepth++; - coverStack.push_back(false); - } else if (isControlFlowEnd(inst)) { - if (currDepth == 0) { - // Less deep than the start, so we found no problem. - return true; - } - currDepth--; - - if (coverStack.back()) { - // A cover existed in the scope which ended. - covers--; - } - coverStack.pop_back(); - } else if (isControlFlowBarrier(inst)) { - // A barrier, like the else in an if-else, not only ends a scope but - // opens a new one. - if (currDepth == 0) { - // Another scope with the same depth begins, but ours ended, so stop. - return true; - } - - if (coverStack.back()) { - // A cover existed in the scope which ended. - covers--; - } - coverStack.back() = false; - } else if (auto* otherSet = inst->origin->dynCast()) { - // We are covered in this scope henceforth. - if (otherSet->index == set->index) { - if (!coverStack.back()) { - covers++; - if (currDepth == 0) { - // We have a cover at depth 0, so everything from here on out - // will be covered. - return true; - } - coverStack.back() = true; - } - } - } else if (auto* otherGet = inst->origin->dynCast()) { - if (otherGet->index == set->index && i != getIndex && !covers) { - // We found a get that might be a problem: it uses the same index, but - // is not the get we were told about, and no other set covers us. - return false; - } - } - } - - // No problem. - return true; - } -}; - -struct OptimizeStackIR : public WalkerPass> { - bool isFunctionParallel() override { return true; } - - std::unique_ptr create() override { - return std::make_unique(); - } - - bool modifiesBinaryenIR() override { return false; } - - void doWalkFunction(Function* func) { - if (!func->stackIR) { - return; - } - StackIROptimizer(func, getPassOptions(), getModule()->features).run(); - } -}; - -Pass* createOptimizeStackIRPass() { return new OptimizeStackIR(); } - -} // namespace wasm diff --git a/src/passes/passes.h b/src/passes/passes.h index 8695539b3ef..ac3e1ef299b 100644 --- a/src/passes/passes.h +++ b/src/passes/passes.h @@ -54,7 +54,6 @@ Pass* createFunctionMetricsPass(); Pass* createGenerateDynCallsPass(); Pass* createGenerateI64DynCallsPass(); Pass* createGenerateGlobalEffectsPass(); -Pass* createGenerateStackIRPass(); Pass* createGlobalRefiningPass(); Pass* createGlobalStructInferencePass(); Pass* createGlobalTypeOptimizationPass(); @@ -103,7 +102,6 @@ Pass* createOptimizeAddedConstantsPropagatePass(); Pass* createOptimizeInstructionsPass(); Pass* createOptimizeCastsPass(); Pass* createOptimizeForJSPass(); -Pass* createOptimizeStackIRPass(); // Outlining currently relies on LLVM's SuffixTree, which we can't rely upon // when building Binaryen for Emscripten. #ifdef __EMSCRIPTEN__ @@ -123,7 +121,6 @@ Pass* createPrinterPass(); Pass* createPrintCallGraphPass(); Pass* createPrintFeaturesPass(); Pass* createPrintFunctionMapPass(); -Pass* createPrintStackIRPass(); Pass* createPropagateGlobalsGloballyPass(); Pass* createRemoveNonJSOpsPass(); Pass* createRemoveImportsPass(); diff --git a/src/wasm-stack.h b/src/wasm-stack.h index 0b72774b618..a5cb07a7d1a 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -525,6 +525,33 @@ class StackIRToBinaryWriter { bool sourceMap; }; +// Stack IR optimizer +class StackIROptimizer { + Function* func; + PassOptions& passOptions; + StackIR& insts; + FeatureSet features; + +public: + StackIROptimizer(Function* func, + PassOptions& passOptions, + FeatureSet features); + + void run(); + +private: + void dce(); + void vacuum(); + void local2Stack(); + void removeUnneededBlocks(); + bool isControlFlowBarrier(StackInst* inst);bool isControlFlowBegin(StackInst* inst); + bool isControlFlowEnd(StackInst* inst); + bool isControlFlow(StackInst* inst); + void removeAt(Index i); + Index getNumConsumedValues(StackInst* inst); + bool canRemoveSetGetPair(Index setIndex, Index getIndex) { +}; + std::ostream& printStackIR(std::ostream& o, Module* module, bool optimize); } // namespace wasm diff --git a/src/wasm/CMakeLists.txt b/src/wasm/CMakeLists.txt index d5b4f674741..e01be3b6a79 100644 --- a/src/wasm/CMakeLists.txt +++ b/src/wasm/CMakeLists.txt @@ -11,6 +11,7 @@ set(wasm_SOURCES wasm-ir-builder.cpp wasm-s-parser.cpp wasm-stack.cpp + wasm-stack-opts.cpp wasm-type.cpp wasm-validator.cpp ${wasm_HEADERS} diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index d7c052a9f61..23283511128 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -403,6 +403,19 @@ void WasmBinaryWriter::writeFunctions() { size_t sizePos = writeU32LEBPlaceholder(); size_t start = o.size(); BYN_TRACE("writing" << func->name << std::endl); + + + StackIRGenerator stackIRGen(*getModule(), func); + stackIRGen.write(); + func->stackIR = std::make_unique(); + func->stackIR->swap(stackIRGen.getStackIR()); + if (optimizeStackIR) { + .. + } + if (printStackIR) { // from a wasm-opt commandline flag + .. + } + // Emit Stack IR if present, and if we can if (func->stackIR) { BYN_TRACE("write Stack IR\n"); diff --git a/src/wasm/wasm-stack-opts.cpp b/src/wasm/wasm-stack-opts.cpp new file mode 100644 index 00000000000..8a6229ff020 --- /dev/null +++ b/src/wasm/wasm-stack-opts.cpp @@ -0,0 +1,450 @@ +/* + * Copyright 2018 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// Operations on Stack IR. +// + +#include "ir/iteration.h" +#include "ir/local-graph.h" +#include "pass.h" +#include "wasm-stack.h" +#include "wasm.h" + +namespace wasm { + +StackIROptimizer::StackIROptimizer(Function* func, + PassOptions& passOptions, + FeatureSet features) + : func(func), passOptions(passOptions), insts(*func->stackIR.get()), + features(features) { + assert(func->stackIR); // TODO move out of func +} + +void StackIROptimizer::run() { + dce(); + // FIXME: local2Stack is currently rather slow (due to localGraph), + // so for now run it only when really optimizing + if (passOptions.optimizeLevel >= 3 || passOptions.shrinkLevel >= 1) { + local2Stack(); + } + removeUnneededBlocks(); + dce(); + vacuum(); +} + +// Remove unreachable code. +void StackIROptimizer::dce() { + bool inUnreachableCode = false; + for (Index i = 0; i < insts.size(); i++) { + auto* inst = insts[i]; + if (!inst) { + continue; + } + if (inUnreachableCode) { + // Does the unreachable code end here? + if (isControlFlowBarrier(inst)) { + inUnreachableCode = false; + } else { + // We can remove this. + removeAt(i); + } + } else if (inst->type == Type::unreachable) { + inUnreachableCode = true; + } + } +} + +// Remove obviously-unneeded code. +void StackIROptimizer::vacuum() { + // In the wasm binary format a nop is never needed. (In Binaryen IR, in + // comparison, it is necessary e.g. in a function body or an if arm.) + // + // It is especially important to remove nops because we add nops when we + // read wasm into Binaryen IR. That is, this avoids a potential increase in + // code size. + for (Index i = 0; i < insts.size(); i++) { + auto*& inst = insts[i]; + if (inst && inst->origin->is()) { + inst = nullptr; + } + } +} + +// If ordered properly, we can avoid a local.set/local.get pair, +// and use the value directly from the stack, for example +// [..produce a value on the stack..] +// local.set $x +// [..much code..] +// local.get $x +// call $foo ;; use the value, foo(value) +// As long as the code in between does not modify $x, and has +// no control flow branching out, we can remove both the set +// and the get. +void StackIROptimizer::local2Stack() { + // We use the localGraph to tell us if a get-set pair is indeed + // a set that is read by that get, and only that get. Note that we run + // this on the Binaryen IR, so we are assuming that no previous opt + // has changed the interaction of local operations. + // TODO: we can do this a lot faster, as we just care about linear + // control flow. + LocalGraph localGraph(func); + localGraph.computeSetInfluences(); + // We maintain a stack of relevant values. This contains: + // * a null for each actual value that the value stack would have + // * an index of each LocalSet that *could* be on the value + // stack at that location. + const Index null = -1; + std::vector values; + // We also maintain a stack of values vectors for control flow, + // saving the stack as we enter and restoring it when we exit. + std::vector> savedValues; +#ifdef STACK_OPT_DEBUG + std::cout << "func: " << func->name << '\n' << insts << '\n'; +#endif + for (Index instIndex = 0; instIndex < insts.size(); instIndex++) { + auto* inst = insts[instIndex]; + if (!inst) { + continue; + } + // First, consume values from the stack as required. + auto consumed = getNumConsumedValues(inst); +#ifdef STACK_OPT_DEBUG + std::cout << " " << instIndex << " : " << *inst << ", " << values.size() + << " on stack, will consume " << consumed << "\n "; + for (auto s : values) + std::cout << s << ' '; + std::cout << '\n'; +#endif + // TODO: currently we run dce before this, but if we didn't, we'd need + // to handle unreachable code here - it's ok to pop multiple values + // there even if the stack is at size 0. + while (consumed > 0) { + assert(values.size() > 0); + // Whenever we hit a possible stack value, kill it - it would + // be consumed here, so we can never optimize to it. + while (values.back() != null) { + values.pop_back(); + assert(values.size() > 0); + } + // Finally, consume the actual value that is consumed here. + values.pop_back(); + consumed--; + } + // After consuming, we can see what to do with this. First, handle + // control flow. + if (isControlFlowBegin(inst)) { + // Save the stack for when we end this control flow. + savedValues.push_back(values); // TODO: optimize copies + values.clear(); + } else if (isControlFlowEnd(inst)) { + assert(!savedValues.empty()); + values = savedValues.back(); + savedValues.pop_back(); + } else if (isControlFlow(inst)) { + // Otherwise, in the middle of control flow, just clear it + values.clear(); + } + // This is something we should handle, look into it. + if (inst->type.isConcrete()) { + bool optimized = false; + // Do not optimize multivalue locals, since those will be better + // optimized when they are visited in the binary writer and this + // optimization would intefere with that one. + if (auto* get = inst->origin->dynCast(); + get && inst->type.isSingle()) { + // Use another local to clarify what instIndex means in this scope. + auto getIndex = instIndex; + + // This is a potential optimization opportunity! See if we + // can reach the set. + if (values.size() > 0) { + Index j = values.size() - 1; + while (1) { + // If there's an actual value in the way, we've failed. + auto setIndex = values[j]; + if (setIndex == null) { + break; + } + auto* set = insts[setIndex]->origin->cast(); + if (set->index == get->index) { + // This might be a proper set-get pair, where the set is + // used by this get and nothing else, check that. + auto& sets = localGraph.getSetses[get]; + if (sets.size() == 1 && *sets.begin() == set) { + auto& setInfluences = localGraph.setInfluences[set]; + // If this has the proper value of 1, also do the potentially- + // expensive check of whether we can remove this pair at all. + if (setInfluences.size() == 1 && + canRemoveSetGetPair(setIndex, getIndex)) { + assert(*setInfluences.begin() == get); + // Do it! The set and the get can go away, the proper + // value is on the stack. +#ifdef STACK_OPT_DEBUG + std::cout << " stackify the get\n"; +#endif + insts[setIndex] = nullptr; + insts[getIndex] = nullptr; + // Continuing on from here, replace this on the stack + // with a null, representing a regular value. We + // keep possible values above us active - they may + // be optimized later, as they would be pushed after + // us, and used before us, so there is no conflict. + values[j] = null; + optimized = true; + break; + } + } + } + // We failed here. Can we look some more? + if (j == 0) { + break; + } + j--; + } + } + } + if (!optimized) { + // This is an actual regular value on the value stack. + values.push_back(null); + } + } else if (inst->origin->is() && inst->type == Type::none) { + // This set is potentially optimizable later, add to stack. + values.push_back(instIndex); + } + } +} + +// There may be unnecessary blocks we can remove: blocks +// without branches to them are always ok to remove. +// TODO: a branch to a block in an if body can become +// a branch to that if body +void StackIROptimizer::removeUnneededBlocks() { + for (auto*& inst : insts) { + if (!inst) { + continue; + } + if (auto* block = inst->origin->dynCast()) { + if (!BranchUtils::BranchSeeker::has(block, block->name)) { + // TODO optimize, maybe run remove-unused-names + inst = nullptr; + } + } + } +} + +// A control flow "barrier" - a point where stack machine +// unreachability ends. +bool StackIROptimizer::isControlFlowBarrier(StackInst* inst) { + switch (inst->op) { + case StackInst::BlockEnd: + case StackInst::IfElse: + case StackInst::IfEnd: + case StackInst::LoopEnd: + case StackInst::Catch: + case StackInst::CatchAll: + case StackInst::Delegate: + case StackInst::TryEnd: + case StackInst::TryTableEnd: { + return true; + } + default: { return false; } + } +} + +// A control flow beginning. +bool StackIROptimizer::isControlFlowBegin(StackInst* inst) { + switch (inst->op) { + case StackInst::BlockBegin: + case StackInst::IfBegin: + case StackInst::LoopBegin: + case StackInst::TryBegin: + case StackInst::TryTableBegin: { + return true; + } + default: { return false; } + } +} + +// A control flow ending. +bool StackIROptimizer::isControlFlowEnd(StackInst* inst) { + switch (inst->op) { + case StackInst::BlockEnd: + case StackInst::IfEnd: + case StackInst::LoopEnd: + case StackInst::TryEnd: + case StackInst::Delegate: + case StackInst::TryTableEnd: { + return true; + } + default: { return false; } + } +} + +bool StackIROptimizer::isControlFlow(StackInst* inst) { return inst->op != StackInst::Basic; } + +// Remove the instruction at index i. If the instruction +// is control flow, and so has been expanded to multiple +// instructions, remove them as well. +void StackIROptimizer::removeAt(Index i) { + auto* inst = insts[i]; + insts[i] = nullptr; + if (inst->op == StackInst::Basic) { + return; // that was it + } + auto* origin = inst->origin; + while (1) { + i++; + assert(i < insts.size()); + inst = insts[i]; + insts[i] = nullptr; + if (inst && inst->origin == origin && isControlFlowEnd(inst)) { + return; // that's it, we removed it all + } + } +} + +Index StackIROptimizer::getNumConsumedValues(StackInst* inst) { + if (isControlFlow(inst)) { + // If consumes 1; that's it. + if (inst->op == StackInst::IfBegin) { + return 1; + } + return 0; + } + // Otherwise, for basic instructions, just count the expression children. + return ChildIterator(inst->origin).children.size(); +} + +// Given a pair of a local.set and local.get, see if we can remove them +// without breaking validation. Specifically, we must keep sets of non- +// nullable locals that dominate a get until the end of the block, such as +// here: +// +// local.set 0 ;; Can we remove +// local.get 0 ;; this pair? +// if +// local.set 0 +// else +// local.set 0 +// end +// local.get 0 ;; This get poses a problem. +// +// Logically the 2nd&3rd sets ensure a value is applied to the local before we +// read it, but the validation rules only track each set until the end of its +// scope, so the 1st set (before the if, in the pair) is necessary. +// +// The logic below is related to LocalStructuralDominance, but sharing code +// with it is difficult as this uses StackIR and not BinaryenIR, and it checks +// a particular set/get pair. +// +// We are given the indexes of the set and get instructions in |insts|. +bool StackIROptimizer::canRemoveSetGetPair(Index setIndex, Index getIndex) { + // The set must be before the get. + assert(setIndex < getIndex); + + auto* set = insts[setIndex]->origin->cast(); + auto localType = func->getLocalType(set->index); + // Note we do not need to handle tuples here, as the parent ignores them + // anyhow (hence we can check non-nullability instead of non- + // defaultability). + assert(localType.isSingle()); + if (func->isParam(set->index) || !localType.isNonNullable()) { + // This local cannot pose a problem for validation (params are always + // initialized, and it is ok if nullable locals are uninitialized). + return true; + } + + // Track the depth (in block/if/loop/etc. scopes) relative to our starting + // point. Anything less deep than that is not interesting, as we can only + // help things at our depth or deeper to validate. + Index currDepth = 0; + + // Look for a different get than the one in getIndex (since that one is + // being removed) which would stop validating without the set. While doing + // so, note other sets that ensure validation even if our set is removed. We + // track those in this stack of booleans, one for each scope, which is true + // if another sets covers us and ours is not needed. + // + // We begin in the current scope and with no other set covering us. + std::vector coverStack = {false}; + + // Track the total number of covers as well, for quick checking below. + Index covers = 0; + + // TODO: We could look before us as well, but then we might end up scanning + // much of the function every time. + for (Index i = setIndex + 1; i < insts.size(); i++) { + auto* inst = insts[i]; + if (!inst) { + continue; + } + if (isControlFlowBegin(inst)) { + // A new scope begins. + currDepth++; + coverStack.push_back(false); + } else if (isControlFlowEnd(inst)) { + if (currDepth == 0) { + // Less deep than the start, so we found no problem. + return true; + } + currDepth--; + + if (coverStack.back()) { + // A cover existed in the scope which ended. + covers--; + } + coverStack.pop_back(); + } else if (isControlFlowBarrier(inst)) { + // A barrier, like the else in an if-else, not only ends a scope but + // opens a new one. + if (currDepth == 0) { + // Another scope with the same depth begins, but ours ended, so stop. + return true; + } + + if (coverStack.back()) { + // A cover existed in the scope which ended. + covers--; + } + coverStack.back() = false; + } else if (auto* otherSet = inst->origin->dynCast()) { + // We are covered in this scope henceforth. + if (otherSet->index == set->index) { + if (!coverStack.back()) { + covers++; + if (currDepth == 0) { + // We have a cover at depth 0, so everything from here on out + // will be covered. + return true; + } + coverStack.back() = true; + } + } + } else if (auto* otherGet = inst->origin->dynCast()) { + if (otherGet->index == set->index && i != getIndex && !covers) { + // We found a get that might be a problem: it uses the same index, but + // is not the get we were told about, and no other set covers us. + return false; + } + } + } + + // No problem. + return true; +} + +} // namespace wasm From efd775b5e15e7430718c2e5939091a4fc569b314 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 09:53:27 -0700 Subject: [PATCH 02/77] work --- src/passes/pass.cpp | 123 --------------------------------------- src/wasm/wasm-binary.cpp | 3 +- 2 files changed, 2 insertions(+), 124 deletions(-) diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index 4a4a9c558a8..488ab018248 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -178,8 +178,6 @@ void PassRegistry::registerPasses() { registerPass("generate-global-effects", "generate global effect info (helps later passes)", createGenerateGlobalEffectsPass); - registerPass( - "generate-stack-ir", "generate Stack IR", createGenerateStackIRPass); registerPass( "global-refining", "refine the types of globals", createGlobalRefiningPass); registerPass( @@ -321,8 +319,6 @@ void PassRegistry::registerPasses() { registerPass("optimize-instructions", "optimizes instruction combinations", createOptimizeInstructionsPass); - registerPass( - "optimize-stack-ir", "optimize Stack IR", createOptimizeStackIRPass); // Outlining currently relies on LLVM's SuffixTree, which we can't rely upon // when building Binaryen for Emscripten. #ifndef SKIP_OUTLINING @@ -369,9 +365,6 @@ void PassRegistry::registerPasses() { registerPass( "symbolmap", "(alias for print-function-map)", createPrintFunctionMapPass); - registerPass("print-stack-ir", - "print out Stack IR (useful for internal debugging)", - createPrintStackIRPass); registerPass("propagate-globals-globally", "propagate global values to other globals (useful for tests)", createPropagateGlobalsGloballyPass); @@ -908,100 +901,6 @@ void PassRunner::doAdd(std::unique_ptr pass) { void PassRunner::clear() { passes.clear(); } -// Checks that the state is valid before and after a -// pass runs on a function. We run these extra checks when -// pass-debug mode is enabled. -struct AfterEffectFunctionChecker { - Function* func; - Name name; - - // Check Stack IR state: if the main IR changes, there should be no - // stack IR, as the stack IR would be wrong. - bool beganWithStackIR; - size_t originalFunctionHash; - - // In the creator we can scan the state of the module and function before the - // pass runs. - AfterEffectFunctionChecker(Function* func) : func(func), name(func->name) { - beganWithStackIR = func->stackIR != nullptr; - if (beganWithStackIR) { - originalFunctionHash = FunctionHasher::hashFunction(func); - } - } - - // This is called after the pass is run, at which time we can check things. - void check() { - assert(func->name == name); // no global module changes should have occurred - if (beganWithStackIR && func->stackIR) { - auto after = FunctionHasher::hashFunction(func); - if (after != originalFunctionHash) { - Fatal() << "[PassRunner] PASS_DEBUG check failed: had Stack IR before " - "and after the pass ran, and the pass modified the main IR, " - "which invalidates Stack IR - pass should have been marked " - "'modifiesBinaryenIR'"; - } - } - } -}; - -// Runs checks on the entire module, in a non-function-parallel pass. -// In particular, in such a pass functions may be removed or renamed, track -// that. -struct AfterEffectModuleChecker { - Module* module; - - std::vector checkers; - - bool beganWithAnyStackIR; - - AfterEffectModuleChecker(Module* module) : module(module) { - for (auto& func : module->functions) { - checkers.emplace_back(func.get()); - } - beganWithAnyStackIR = hasAnyStackIR(); - } - - void check() { - if (beganWithAnyStackIR && hasAnyStackIR()) { - // If anything changed to the functions, that's not good. - if (checkers.size() != module->functions.size()) { - error(); - } - for (Index i = 0; i < checkers.size(); i++) { - // Did a pointer change? (a deallocated function could cause that) - if (module->functions[i].get() != checkers[i].func || - module->functions[i]->body != checkers[i].func->body) { - error(); - } - // Did a name change? - if (module->functions[i]->name != checkers[i].name) { - error(); - } - } - // Global function state appears to not have been changed: the same - // functions are there. Look into their contents. - for (auto& checker : checkers) { - checker.check(); - } - } - } - - void error() { - Fatal() << "[PassRunner] PASS_DEBUG check failed: had Stack IR before and " - "after the pass ran, and the pass modified global function " - "state - pass should have been marked 'modifiesBinaryenIR'"; - } - - bool hasAnyStackIR() { - for (auto& func : module->functions) { - if (func->stackIR) { - return true; - } - } - return false; - } -}; - void PassRunner::runPass(Pass* pass) { assert(!pass->isFunctionParallel()); @@ -1009,20 +908,11 @@ void PassRunner::runPass(Pass* pass) { return; } - std::unique_ptr checker; - if (getPassDebug()) { - checker = std::unique_ptr( - new AfterEffectModuleChecker(wasm)); - } // Passes can only be run once and we deliberately do not clear the pass // runner after running the pass, so there must not already be a runner here. assert(!pass->getPassRunner()); pass->setPassRunner(this); pass->run(wasm); - handleAfterEffects(pass); - if (getPassDebug()) { - checker->check(); - } } void PassRunner::runPassOnFunction(Pass* pass, Function* func) { @@ -1051,21 +941,12 @@ void PassRunner::runPassOnFunction(Pass* pass, Function* func) { bodyBefore << *func->body << '\n'; } - std::unique_ptr checker; - if (passDebug) { - checker = std::make_unique(func); - } - // Function-parallel passes get a new instance per function auto instance = pass->create(); instance->setPassRunner(this); instance->runOnFunction(wasm, func); handleAfterEffects(pass, func); - if (passDebug) { - checker->check(); - } - if (extraFunctionValidation) { if (!WasmValidator().validate(func, *wasm, WasmValidator::Minimal)) { Fatal() << "Last nested function-parallel pass (" << pass->name @@ -1095,10 +976,6 @@ void PassRunner::handleAfterEffects(Pass* pass, Function* func) { return; } - // If Binaryen IR is modified, Stack IR must be cleared - it would - // be out of sync in a potentially dangerous way. - func->stackIR.reset(nullptr); - if (pass->requiresNonNullableLocalFixups()) { TypeUpdating::handleNonDefaultableLocals(func, *wasm); } diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 23283511128..18c267f3047 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -410,7 +410,8 @@ void WasmBinaryWriter::writeFunctions() { func->stackIR = std::make_unique(); func->stackIR->swap(stackIRGen.getStackIR()); if (optimizeStackIR) { - .. + StackIROptimizer optimizer(func, passOptions, wasm.features); + optimizer.run(); } if (printStackIR) { // from a wasm-opt commandline flag .. From ae07cd5ed1e42545967cdf79083f93eb9519cb07 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 10:07:20 -0700 Subject: [PATCH 03/77] work --- src/pass.h | 4 ++++ src/tools/tool-options.h | 29 +++++++++++++++++++++++++++-- src/tools/wasm-opt.cpp | 12 +++++++----- src/wasm-binary.h | 4 +++- src/wasm-io.h | 4 +++- src/wasm/wasm-binary.cpp | 23 +++++++++++++---------- src/wasm/wasm-io.cpp | 2 +- 7 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/pass.h b/src/pass.h index 2c2fa06190c..2021b917395 100644 --- a/src/pass.h +++ b/src/pass.h @@ -219,6 +219,10 @@ struct PassOptions { bool closedWorld = false; // Whether to try to preserve debug info through, which are special calls. bool debugInfo = false; + // TODO comment + bool generateStackIR = false; + bool optimizeStackIR = false; + bool printStackIR = false; // Whether we are targeting JS. In that case we want to avoid emitting things // in the optimizer that do not translate well to JS, or that could cause us // to need extra lowering work or even a loop (where we optimize to something diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h index 6d68ff3c1ec..8b153b36f39 100644 --- a/src/tools/tool-options.h +++ b/src/tools/tool-options.h @@ -151,7 +151,26 @@ struct ToolOptions : public Options { Options::Arguments::Zero, [this](Options*, const std::string&) { passOptions.closedWorld = true; - }); + }) + .add("--generate-stack-ir", + "", + "generate StackIR during writing", + WasmOptOption, + Options::Arguments::Zero, + [&](Options* o, const std::string& arguments) { passOptions.generateStackIR = false; }) + .add("--optimize-stack-ir", + "", + "optimize StackIR during writing", + WasmOptOption, + Options::Arguments::Zero, + [&](Options* o, const std::string& arguments) { passOptions.optimizeStackIR = false; }) + .add("--print-stack-ir", + "", + "print StackIR during writing", + WasmOptOption, + Options::Arguments::Zero, + [&](Options* o, const std::string& arguments) { passOptions.printStackIR = false; }) + ; } ToolOptions& addFeature(FeatureSet::Feature feature, @@ -179,9 +198,15 @@ struct ToolOptions : public Options { return *this; } - void applyFeatures(Module& module) const { + void applyFeatures(Module& module) { // TODO rename? module.features.enable(enabledFeatures); module.features.disable(disabledFeatures); + + if (passOptions.optimizeLevel >= 2 || + passOptions.shrinkLevel >= 1) { + passOptions.generateStackIR = true; + passOptions.optimizeStackIR = true; + } } private: diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index 32f9f1aaddb..fdff1fe2627 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -178,6 +178,13 @@ int main(int argc, const char* argv[]) { WasmOptOption, Options::Arguments::Zero, [&](Options* o, const std::string& arguments) { fuzzOOB = false; }) + .add("--no-fuzz-oob", + "", + "don't emit out-of-bounds loads/stores/indirect calls when fuzzing", + WasmOptOption, + Options::Arguments::Zero, + [&](Options* o, const std::string& arguments) { fuzzOOB = false; }) + .add("--emit-spec-wrapper", "-esw", "Emit a wasm spec interpreter wrapper file that can run the wasm with " @@ -402,11 +409,6 @@ int main(int argc, const char* argv[]) { runner.add("translate-to-new-eh"); // Perform Stack IR optimizations here, at the very end of the // optimization pipeline. - if (options.passOptions.optimizeLevel >= 2 || - options.passOptions.shrinkLevel >= 1) { - runner.addIfNoDWARFIssues("generate-stack-ir"); - runner.addIfNoDWARFIssues("optimize-stack-ir"); - } runner.run(); if (options.passOptions.validate) { bool valid = WasmValidator().validate(wasm, options.passOptions); diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 6fd082f797c..7af27126691 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1270,7 +1270,7 @@ class WasmBinaryWriter { }; public: - WasmBinaryWriter(Module* input, BufferWithRandomAccess& o) + WasmBinaryWriter(Module* input, BufferWithRandomAccess& o, const PassOptions& options) : wasm(input), o(o), indexes(*input) { prepare(); } @@ -1383,6 +1383,8 @@ class WasmBinaryWriter { private: Module* wasm; BufferWithRandomAccess& o; + const PassOptions& options; + BinaryIndexes indexes; ModuleUtils::IndexedHeapTypes indexedTypes; std::unordered_map signatureIndexes; diff --git a/src/wasm-io.h b/src/wasm-io.h index ae66c39320d..d52f0162c90 100644 --- a/src/wasm-io.h +++ b/src/wasm-io.h @@ -85,6 +85,8 @@ class ModuleReader : public ModuleIOBase { }; class ModuleWriter : public ModuleIOBase { + const PassOptions& options; + bool binary = true; // TODO: Remove `emitModuleName`. See the comment in wasm-binary.h @@ -97,7 +99,7 @@ class ModuleWriter : public ModuleIOBase { public: // Writing defaults to not storing the names section. Storing it is a user- // observable fact that must be opted into. - ModuleWriter() { setDebugInfo(false); } + ModuleWriter(const PassOptions& options) : options(options) { setDebugInfo(false); } void setBinary(bool binary_) { binary = binary_; } void setSymbolMap(std::string symbolMap_) { symbolMap = symbolMap_; } diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 18c267f3047..bbee6142723 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -404,17 +404,20 @@ void WasmBinaryWriter::writeFunctions() { size_t start = o.size(); BYN_TRACE("writing" << func->name << std::endl); + if (options.generateStackIR) { + StackIRGenerator stackIRGen(*getModule(), func); + stackIRGen.write(); + func->stackIR = std::make_unique(); + func->stackIR->swap(stackIRGen.getStackIR()); - StackIRGenerator stackIRGen(*getModule(), func); - stackIRGen.write(); - func->stackIR = std::make_unique(); - func->stackIR->swap(stackIRGen.getStackIR()); - if (optimizeStackIR) { - StackIROptimizer optimizer(func, passOptions, wasm.features); - optimizer.run(); - } - if (printStackIR) { // from a wasm-opt commandline flag - .. + if (options.optimizeStackIR) { + StackIROptimizer optimizer(func, passOptions, wasm.features); + optimizer.run(); + } + + if (options.printStackIR) { // from a wasm-opt commandline flag + .. + } } // Emit Stack IR if present, and if we can diff --git a/src/wasm/wasm-io.cpp b/src/wasm/wasm-io.cpp index a24122bd8d6..10b84bb4dd0 100644 --- a/src/wasm/wasm-io.cpp +++ b/src/wasm/wasm-io.cpp @@ -149,7 +149,7 @@ void ModuleWriter::writeText(Module& wasm, std::string filename) { void ModuleWriter::writeBinary(Module& wasm, Output& output) { BufferWithRandomAccess buffer; - WasmBinaryWriter writer(&wasm, buffer); + WasmBinaryWriter writer(&wasm, buffer, options); // if debug info is used, then we want to emit the names section writer.setNamesSection(debugInfo); if (emitModuleName) { From 37e1a40f5714f5200732f1fdc407db7d4b987899 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 10:08:49 -0700 Subject: [PATCH 04/77] yolo --- src/passes/Print.cpp | 6 +----- src/wasm-stack.h | 2 +- src/wasm/wasm-binary.cpp | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index b30a1180d2f..08970a35260 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -3603,12 +3603,8 @@ static std::ostream& printStackIR(StackIR* ir, PrintSExpression& printer) { return o; } -std::ostream& printStackIR(std::ostream& o, Module* module, bool optimize) { +std::ostream& printStackIR(std::ostream& o, Module* module) { wasm::PassRunner runner(module); - runner.add("generate-stack-ir"); - if (optimize) { - runner.add("optimize-stack-ir"); - } runner.add(std::make_unique(&o)); runner.run(); return o; diff --git a/src/wasm-stack.h b/src/wasm-stack.h index a5cb07a7d1a..d8e91dce341 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -552,7 +552,7 @@ class StackIROptimizer { bool canRemoveSetGetPair(Index setIndex, Index getIndex) { }; -std::ostream& printStackIR(std::ostream& o, Module* module, bool optimize); +std::ostream& printStackIR(std::ostream& o, Module* module); } // namespace wasm diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index bbee6142723..978126c3131 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -416,7 +416,7 @@ void WasmBinaryWriter::writeFunctions() { } if (options.printStackIR) { // from a wasm-opt commandline flag - .. + printStackIR(std::cout, *wasm); } } From 2a29c467f3c93ecd79f9c5c742baa6345aa9adb5 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 10:11:35 -0700 Subject: [PATCH 05/77] work --- src/passes/pass.cpp | 8 ++++---- src/wasm-binary.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index 488ab018248..8bb917efe3f 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -737,7 +737,7 @@ void PassRunner::addDefaultGlobalOptimizationPostPasses() { } } -static void dumpWasm(Name name, Module* wasm) { +static void dumpWasm(Name name, Module* wasm, const PassOptions& options) { static int counter = 0; std::string numstr = std::to_string(counter++); while (numstr.size() < 3) { @@ -750,7 +750,7 @@ static void dumpWasm(Name name, Module* wasm) { #endif fullName += numstr + "-" + name.toString(); Colors::setEnabled(false); - ModuleWriter writer; + ModuleWriter writer(options); writer.setDebugInfo(true); writer.writeBinary(*wasm, fullName + ".wasm"); } @@ -773,7 +773,7 @@ void PassRunner::run() { padding = std::max(padding, pass->name.size()); } if (passDebug >= 3 && !isNested) { - dumpWasm("before", wasm); + dumpWasm("before", wasm, options); } for (auto& pass : passes) { // ignoring the time, save a printout of the module before, in case this @@ -817,7 +817,7 @@ void PassRunner::run() { } } if (passDebug >= 3) { - dumpWasm(pass->name, wasm); + dumpWasm(pass->name, wasm, options); } } std::cerr << "[PassRunner] " << what << " took " << totalTime.count() diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 7af27126691..310b251c177 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1271,7 +1271,7 @@ class WasmBinaryWriter { public: WasmBinaryWriter(Module* input, BufferWithRandomAccess& o, const PassOptions& options) - : wasm(input), o(o), indexes(*input) { + : wasm(input), o(o), options(options), indexes(*input) { prepare(); } From a60e77ed877d97ae74ca8ba5ec4c28440dff4123 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 10:23:11 -0700 Subject: [PATCH 06/77] work --- src/tools/tool-options.h | 6 +++--- src/wasm-stack.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h index 8b153b36f39..648f501a796 100644 --- a/src/tools/tool-options.h +++ b/src/tools/tool-options.h @@ -155,19 +155,19 @@ struct ToolOptions : public Options { .add("--generate-stack-ir", "", "generate StackIR during writing", - WasmOptOption, + ToolOptionsCategory, Options::Arguments::Zero, [&](Options* o, const std::string& arguments) { passOptions.generateStackIR = false; }) .add("--optimize-stack-ir", "", "optimize StackIR during writing", - WasmOptOption, + ToolOptionsCategory, Options::Arguments::Zero, [&](Options* o, const std::string& arguments) { passOptions.optimizeStackIR = false; }) .add("--print-stack-ir", "", "print StackIR during writing", - WasmOptOption, + ToolOptionsCategory, Options::Arguments::Zero, [&](Options* o, const std::string& arguments) { passOptions.printStackIR = false; }) ; diff --git a/src/wasm-stack.h b/src/wasm-stack.h index d8e91dce341..abffaa6cc09 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -549,7 +549,7 @@ class StackIROptimizer { bool isControlFlow(StackInst* inst); void removeAt(Index i); Index getNumConsumedValues(StackInst* inst); - bool canRemoveSetGetPair(Index setIndex, Index getIndex) { + bool canRemoveSetGetPair(Index setIndex, Index getIndex); }; std::ostream& printStackIR(std::ostream& o, Module* module); From b1a214eb3ec025a157cb0fb9fa35b57f3e89c772 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 10:25:08 -0700 Subject: [PATCH 07/77] work --- src/passes/Metrics.cpp | 6 +++--- src/passes/RoundTrip.cpp | 2 +- src/wasm-io.h | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/passes/Metrics.cpp b/src/passes/Metrics.cpp index d2e072a6f99..1778eb9bd09 100644 --- a/src/passes/Metrics.cpp +++ b/src/passes/Metrics.cpp @@ -94,7 +94,7 @@ struct Metrics printCounts("global"); // compute binary info, so we know function sizes BufferWithRandomAccess buffer; - WasmBinaryWriter writer(module, buffer); + WasmBinaryWriter writer(module, buffer, getPassOptions()); writer.write(); // print for each function Index binaryIndex = 0; @@ -108,14 +108,14 @@ struct Metrics }); // print for each export how much code size is due to it, i.e., // how much the module could shrink without it. - auto sizeAfterGlobalCleanup = [](Module* module) { + auto sizeAfterGlobalCleanup = [&](Module* module) { PassRunner runner(module, PassOptions::getWithDefaultOptimizationOptions()); runner.setIsNested(true); runner.addDefaultGlobalOptimizationPostPasses(); // remove stuff runner.run(); BufferWithRandomAccess buffer; - WasmBinaryWriter writer(module, buffer); + WasmBinaryWriter writer(module, buffer, getPassOptions()); writer.write(); return buffer.size(); }; diff --git a/src/passes/RoundTrip.cpp b/src/passes/RoundTrip.cpp index b930b195cf9..129b89ac818 100644 --- a/src/passes/RoundTrip.cpp +++ b/src/passes/RoundTrip.cpp @@ -41,7 +41,7 @@ struct RoundTrip : public Pass { // to tell the builder which features to build with. auto features = module->features; // Write, clear, and read the module - WasmBinaryWriter(module, buffer).write(); + WasmBinaryWriter(module, buffer, getPassOptions()).write(); ModuleUtils::clearModule(*module); auto input = buffer.getAsChars(); WasmBinaryReader parser(*module, features, input); diff --git a/src/wasm-io.h b/src/wasm-io.h index d52f0162c90..d8040d8c460 100644 --- a/src/wasm-io.h +++ b/src/wasm-io.h @@ -22,6 +22,7 @@ #define wasm_wasm_io_h #include "parsing.h" +#include "pass.h" #include "support/file.h" #include "wasm.h" From 5c79fc425312514f77e2b414e8ff8e67f7a1ac0f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 10:29:25 -0700 Subject: [PATCH 08/77] work --- src/tools/wasm-as.cpp | 2 +- src/tools/wasm-ctor-eval.cpp | 2 +- src/tools/wasm-emscripten-finalize.cpp | 2 +- src/tools/wasm-merge.cpp | 2 +- src/tools/wasm-metadce.cpp | 2 +- src/tools/wasm-opt.cpp | 6 +++--- src/tools/wasm-reduce.cpp | 4 ++-- src/tools/wasm-split/wasm-split.cpp | 2 +- src/wasm/wasm-binary.cpp | 4 ++-- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/tools/wasm-as.cpp b/src/tools/wasm-as.cpp index 311605326b5..a767e6908e4 100644 --- a/src/tools/wasm-as.cpp +++ b/src/tools/wasm-as.cpp @@ -129,7 +129,7 @@ int main(int argc, const char* argv[]) { if (options.debug) { std::cerr << "writing..." << std::endl; } - ModuleWriter writer; + ModuleWriter writer(options.passOptions); writer.setBinary(true); writer.setDebugInfo(debugInfo); if (sourceMapFilename.size()) { diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 4018be0e72a..d3f7980848d 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -1491,7 +1491,7 @@ int main(int argc, const char* argv[]) { if (options.debug) { std::cout << "writing..." << std::endl; } - ModuleWriter writer; + ModuleWriter writer(options.passOptions); writer.setBinary(emitBinary); writer.setDebugInfo(debugInfo); writer.write(wasm, options.extra["output"]); diff --git a/src/tools/wasm-emscripten-finalize.cpp b/src/tools/wasm-emscripten-finalize.cpp index a19d2732808..6b4e994ac83 100644 --- a/src/tools/wasm-emscripten-finalize.cpp +++ b/src/tools/wasm-emscripten-finalize.cpp @@ -279,7 +279,7 @@ int main(int argc, const char* argv[]) { if (writeOutput) { Output output(outfile, emitBinary ? Flags::Binary : Flags::Text); - ModuleWriter writer; + ModuleWriter writer(options.passOptions); writer.setDebugInfo(debugInfo); // writer.setSymbolMap(symbolMap); writer.setBinary(emitBinary); diff --git a/src/tools/wasm-merge.cpp b/src/tools/wasm-merge.cpp index 8e8e2d80d82..449f0cfdb40 100644 --- a/src/tools/wasm-merge.cpp +++ b/src/tools/wasm-merge.cpp @@ -752,7 +752,7 @@ Input source maps can be specified by adding an -ism option right after the modu // Output. if (options.extra.count("output") > 0) { - ModuleWriter writer; + ModuleWriter writer(options.passOptions); writer.setBinary(emitBinary); writer.setDebugInfo(debugInfo); if (outputSourceMapFilename.size()) { diff --git a/src/tools/wasm-metadce.cpp b/src/tools/wasm-metadce.cpp index 1b429a72331..3014702062f 100644 --- a/src/tools/wasm-metadce.cpp +++ b/src/tools/wasm-metadce.cpp @@ -600,7 +600,7 @@ int main(int argc, const char* argv[]) { graph.apply(); if (options.extra.count("output") > 0) { - ModuleWriter writer; + ModuleWriter writer(options.passOptions); writer.setBinary(emitBinary); writer.setDebugInfo(debugInfo); if (outputSourceMapFilename.size()) { diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index fdff1fe2627..3d6127feab1 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -354,7 +354,7 @@ int main(int argc, const char* argv[]) { if (extraFuzzCommand.size() > 0 && options.extra.count("output") > 0) { BYN_TRACE("writing binary before opts, for extra fuzz command...\n"); - ModuleWriter writer; + ModuleWriter writer(options.passOptions); writer.setBinary(emitBinary); writer.setDebugInfo(options.passOptions.debugInfo); writer.write(wasm, options.extra["output"]); @@ -386,7 +386,7 @@ int main(int argc, const char* argv[]) { // size no longer decreasing. auto getSize = [&]() { BufferWithRandomAccess buffer; - WasmBinaryWriter writer(&wasm, buffer); + WasmBinaryWriter writer(&wasm, buffer, options.passOptions); writer.write(); return buffer.size(); }; @@ -430,7 +430,7 @@ int main(int argc, const char* argv[]) { } BYN_TRACE("writing...\n"); - ModuleWriter writer; + ModuleWriter writer(options.passOptions); writer.setBinary(emitBinary); writer.setDebugInfo(options.passOptions.debugInfo); if (outputSourceMapFilename.size()) { diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp index 094338beab7..002a89ea53b 100644 --- a/src/tools/wasm-reduce.cpp +++ b/src/tools/wasm-reduce.cpp @@ -401,7 +401,7 @@ struct Reducer bool writeAndTestReduction(ProgramResult& out) { // write the module out - ModuleWriter writer; + ModuleWriter writer(options.passOptions); writer.setBinary(binary); writer.setDebugInfo(debugInfo); writer.write(*getModule(), test); @@ -1368,7 +1368,7 @@ int main(int argc, const char* argv[]) { if (resultOnInvalid == expected) { // Try it on a valid input. Module emptyModule; - ModuleWriter writer; + ModuleWriter writer(options.passOptions); writer.setBinary(true); writer.write(emptyModule, test); ProgramResult resultOnValid(command); diff --git a/src/tools/wasm-split/wasm-split.cpp b/src/tools/wasm-split/wasm-split.cpp index bea3ddce71b..d7dc19d677a 100644 --- a/src/tools/wasm-split/wasm-split.cpp +++ b/src/tools/wasm-split/wasm-split.cpp @@ -91,7 +91,7 @@ void adjustTableSize(Module& wasm, int initialSize) { void writeModule(Module& wasm, std::string filename, const WasmSplitOptions& options) { - ModuleWriter writer; + ModuleWriter writer(options.passOptions); writer.setBinary(options.emitBinary); writer.setDebugInfo(options.passOptions.debugInfo); if (options.emitModuleNames) { diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 978126c3131..169017d4804 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -411,12 +411,12 @@ void WasmBinaryWriter::writeFunctions() { func->stackIR->swap(stackIRGen.getStackIR()); if (options.optimizeStackIR) { - StackIROptimizer optimizer(func, passOptions, wasm.features); + StackIROptimizer optimizer(func, options, wasm.features); optimizer.run(); } if (options.printStackIR) { // from a wasm-opt commandline flag - printStackIR(std::cout, *wasm); + printStackIR(std::cout, wasm); } } From 59c984506e4bb8324bbe44a16f4c8df25262dff6 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 10:31:57 -0700 Subject: [PATCH 09/77] work --- src/tools/wasm-reduce.cpp | 2 +- src/tools/wasm-split/wasm-split.cpp | 8 ++++---- src/wasm/wasm-binary.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp index 002a89ea53b..ac5b7722bd3 100644 --- a/src/tools/wasm-reduce.cpp +++ b/src/tools/wasm-reduce.cpp @@ -401,7 +401,7 @@ struct Reducer bool writeAndTestReduction(ProgramResult& out) { // write the module out - ModuleWriter writer(options.passOptions); + ModuleWriter writer(toolOptions.passOptions); writer.setBinary(binary); writer.setDebugInfo(debugInfo); writer.write(*getModule(), test); diff --git a/src/tools/wasm-split/wasm-split.cpp b/src/tools/wasm-split/wasm-split.cpp index d7dc19d677a..3436f5bdcb6 100644 --- a/src/tools/wasm-split/wasm-split.cpp +++ b/src/tools/wasm-split/wasm-split.cpp @@ -37,7 +37,7 @@ using namespace wasm; namespace { -void parseInput(Module& wasm, const WasmSplitOptions& options) { +void parseInput(Module& wasm, WasmSplitOptions& options) { options.applyFeatures(wasm); ModuleReader reader; reader.setProfile(options.profile); @@ -100,7 +100,7 @@ void writeModule(Module& wasm, writer.write(wasm, filename); } -void instrumentModule(const WasmSplitOptions& options) { +void instrumentModule(WasmSplitOptions& options) { Module wasm; parseInput(wasm, options); @@ -207,7 +207,7 @@ void writePlaceholderMap(const std::map placeholderMap, } } -void splitModule(const WasmSplitOptions& options) { +void splitModule(WasmSplitOptions& options) { Module wasm; parseInput(wasm, options); @@ -430,7 +430,7 @@ void checkExists(const std::string& path) { } } -void printReadableProfile(const WasmSplitOptions& options) { +void printReadableProfile(WasmSplitOptions& options) { const std::string wasmFile(options.inputFiles[0]); checkExists(options.profileFile); checkExists(wasmFile); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 169017d4804..86bf846c511 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -411,7 +411,7 @@ void WasmBinaryWriter::writeFunctions() { func->stackIR->swap(stackIRGen.getStackIR()); if (options.optimizeStackIR) { - StackIROptimizer optimizer(func, options, wasm.features); + StackIROptimizer optimizer(func, options, wasm->features); optimizer.run(); } From fa4f18b028a4f5c654a8fd53cc57a6caa37445f8 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 10:35:56 -0700 Subject: [PATCH 10/77] work --- src/binaryen-c.cpp | 6 +++--- src/binaryen-c.h | 3 +-- src/wasm-stack.h | 7 ++++--- src/wasm/wasm-stack-opts.cpp | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index f27f6e2c89c..e68f2c0664e 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -5590,8 +5590,8 @@ void BinaryenModulePrint(BinaryenModuleRef module) { std::cout << *(Module*)module; } -void BinaryenModulePrintStackIR(BinaryenModuleRef module, bool optimize) { - wasm::printStackIR(std::cout, (Module*)module, optimize); +void BinaryenModulePrintStackIR(BinaryenModuleRef module) { + wasm::printStackIR(std::cout, (Module*)module); } void BinaryenModulePrintAsmjs(BinaryenModuleRef module) { @@ -5737,7 +5737,7 @@ static BinaryenBufferSizes writeModule(BinaryenModuleRef module, char* sourceMap, size_t sourceMapSize) { BufferWithRandomAccess buffer; - WasmBinaryWriter writer((Module*)module, buffer); + WasmBinaryWriter writer((Module*)module, buffer, globalPassOptions); writer.setNamesSection(globalPassOptions.debugInfo); std::ostringstream os; if (sourceMapUrl) { diff --git a/src/binaryen-c.h b/src/binaryen-c.h index bc63e963ae1..fadada35635 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -2984,8 +2984,7 @@ BINARYEN_API BinaryenModuleRef BinaryenModuleParse(const char* text); BINARYEN_API void BinaryenModulePrint(BinaryenModuleRef module); // Print a module to stdout in stack IR text format. Useful for debugging. -BINARYEN_API void BinaryenModulePrintStackIR(BinaryenModuleRef module, - bool optimize); +BINARYEN_API void BinaryenModulePrintStackIR(BinaryenModuleRef module); // Print a module to stdout in asm.js syntax. BINARYEN_API void BinaryenModulePrintAsmjs(BinaryenModuleRef module); diff --git a/src/wasm-stack.h b/src/wasm-stack.h index abffaa6cc09..0911148f8e3 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -528,13 +528,13 @@ class StackIRToBinaryWriter { // Stack IR optimizer class StackIROptimizer { Function* func; - PassOptions& passOptions; + const PassOptions& passOptions; StackIR& insts; FeatureSet features; public: StackIROptimizer(Function* func, - PassOptions& passOptions, + const PassOptions& passOptions, FeatureSet features); void run(); @@ -544,7 +544,8 @@ class StackIROptimizer { void vacuum(); void local2Stack(); void removeUnneededBlocks(); - bool isControlFlowBarrier(StackInst* inst);bool isControlFlowBegin(StackInst* inst); + bool isControlFlowBarrier(StackInst* inst); + bool isControlFlowBegin(StackInst* inst); bool isControlFlowEnd(StackInst* inst); bool isControlFlow(StackInst* inst); void removeAt(Index i); diff --git a/src/wasm/wasm-stack-opts.cpp b/src/wasm/wasm-stack-opts.cpp index 8a6229ff020..9e4c10cf56e 100644 --- a/src/wasm/wasm-stack-opts.cpp +++ b/src/wasm/wasm-stack-opts.cpp @@ -27,7 +27,7 @@ namespace wasm { StackIROptimizer::StackIROptimizer(Function* func, - PassOptions& passOptions, + const PassOptions& passOptions, FeatureSet features) : func(func), passOptions(passOptions), insts(*func->stackIR.get()), features(features) { From 88b5079bb440ee31c854861f7070338d001220c6 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 10:37:48 -0700 Subject: [PATCH 11/77] work --- src/binaryen-c.cpp | 12 +++++------- src/binaryen-c.h | 5 ++--- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index e68f2c0664e..f42644047de 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -5778,12 +5778,11 @@ size_t BinaryenModuleWriteText(BinaryenModuleRef module, size_t BinaryenModuleWriteStackIR(BinaryenModuleRef module, char* output, - size_t outputSize, - bool optimize) { + size_t outputSize) { // use a stringstream as an std::ostream. Extract the std::string // representation, and then store in the output. std::stringstream ss; - wasm::printStackIR(ss, (Module*)module, optimize); + wasm::printStackIR(ss, (Module*)module); const auto temp = ss.str(); const auto ctemp = temp.c_str(); @@ -5808,7 +5807,7 @@ BinaryenModuleAllocateAndWriteResult BinaryenModuleAllocateAndWrite(BinaryenModuleRef module, const char* sourceMapUrl) { BufferWithRandomAccess buffer; - WasmBinaryWriter writer((Module*)module, buffer); + WasmBinaryWriter writer((Module*)module, buffer, globalPassOptions); writer.setNamesSection(globalPassOptions.debugInfo); std::ostringstream os; if (sourceMapUrl) { @@ -5842,13 +5841,12 @@ char* BinaryenModuleAllocateAndWriteText(BinaryenModuleRef module) { return output; } -char* BinaryenModuleAllocateAndWriteStackIR(BinaryenModuleRef module, - bool optimize) { +char* BinaryenModuleAllocateAndWriteStackIR(BinaryenModuleRef module) { std::ostringstream os; bool colors = Colors::isEnabled(); Colors::setEnabled(false); // do not use colors for writing - wasm::printStackIR(os, (Module*)module, optimize); + wasm::printStackIR(os, (Module*)module); Colors::setEnabled(colors); // restore colors state auto str = os.str(); diff --git a/src/binaryen-c.h b/src/binaryen-c.h index fadada35635..595086d6a25 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -3125,8 +3125,7 @@ BINARYEN_API size_t BinaryenModuleWriteText(BinaryenModuleRef module, // outputSize BINARYEN_API size_t BinaryenModuleWriteStackIR(BinaryenModuleRef module, char* output, - size_t outputSize, - bool optimize); + size_t outputSize); typedef struct BinaryenBufferSizes { size_t outputBytes; @@ -3172,7 +3171,7 @@ BINARYEN_API char* BinaryenModuleAllocateAndWriteText(BinaryenModuleRef module); // char* with malloc(), and expects the user to free() them manually // once not needed anymore. BINARYEN_API char* -BinaryenModuleAllocateAndWriteStackIR(BinaryenModuleRef module, bool optimize); +BinaryenModuleAllocateAndWriteStackIR(BinaryenModuleRef module); // Deserialize a module from binary form, assuming the MVP feature set. BINARYEN_API BinaryenModuleRef BinaryenModuleRead(char* input, From ae77b602f369ff9cbb3988fc380738c4bce6d1b3 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 10:39:06 -0700 Subject: [PATCH 12/77] work --- src/passes/pass.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index 8bb917efe3f..0d8002f8592 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -729,12 +729,6 @@ void PassRunner::addDefaultGlobalOptimizationPostPasses() { } // may allow more inlining/dae/etc., need --converge for that addIfNoDWARFIssues("directize"); - // perform Stack IR optimizations here, at the very end of the - // optimization pipeline - if (options.optimizeLevel >= 2 || options.shrinkLevel >= 1) { - addIfNoDWARFIssues("generate-stack-ir"); - addIfNoDWARFIssues("optimize-stack-ir"); - } } static void dumpWasm(Name name, Module* wasm, const PassOptions& options) { From b30d8f0914e7cadc566cb4d10f54536f94941c9a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 10:59:07 -0700 Subject: [PATCH 13/77] test --- test/lit/help/wasm-as.test | 6 ++++++ test/lit/help/wasm-ctor-eval.test | 6 ++++++ test/lit/help/wasm-dis.test | 6 ++++++ test/lit/help/wasm-emscripten-finalize.test | 6 ++++++ test/lit/help/wasm-merge.test | 6 ++++++ test/lit/help/wasm-metadce.test | 6 ++++++ test/lit/help/wasm-opt.test | 17 ++++++++++------- test/lit/help/wasm-reduce.test | 6 ++++++ test/lit/help/wasm-split.test | 6 ++++++ test/lit/help/wasm2js.test | 13 ++++++------- 10 files changed, 64 insertions(+), 14 deletions(-) diff --git a/test/lit/help/wasm-as.test b/test/lit/help/wasm-as.test index bf12fc1cf57..09e5b7c9da2 100644 --- a/test/lit/help/wasm-as.test +++ b/test/lit/help/wasm-as.test @@ -126,6 +126,12 @@ ;; CHECK-NEXT: them and pass them back in, but not ;; CHECK-NEXT: inspect their contents or call them. ;; CHECK-NEXT: +;; CHECK-NEXT: --generate-stack-ir generate StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --optimize-stack-ir optimize StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --print-stack-ir print StackIR during writing +;; CHECK-NEXT: ;; CHECK-NEXT: ;; CHECK-NEXT: General options: ;; CHECK-NEXT: ---------------- diff --git a/test/lit/help/wasm-ctor-eval.test b/test/lit/help/wasm-ctor-eval.test index bbf8e1daa3c..e511ef0b9a2 100644 --- a/test/lit/help/wasm-ctor-eval.test +++ b/test/lit/help/wasm-ctor-eval.test @@ -133,6 +133,12 @@ ;; CHECK-NEXT: them and pass them back in, but not ;; CHECK-NEXT: inspect their contents or call them. ;; CHECK-NEXT: +;; CHECK-NEXT: --generate-stack-ir generate StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --optimize-stack-ir optimize StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --print-stack-ir print StackIR during writing +;; CHECK-NEXT: ;; CHECK-NEXT: ;; CHECK-NEXT: General options: ;; CHECK-NEXT: ---------------- diff --git a/test/lit/help/wasm-dis.test b/test/lit/help/wasm-dis.test index f1f8283c8a4..2dffcc945d9 100644 --- a/test/lit/help/wasm-dis.test +++ b/test/lit/help/wasm-dis.test @@ -119,6 +119,12 @@ ;; CHECK-NEXT: them and pass them back in, but not ;; CHECK-NEXT: inspect their contents or call them. ;; CHECK-NEXT: +;; CHECK-NEXT: --generate-stack-ir generate StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --optimize-stack-ir optimize StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --print-stack-ir print StackIR during writing +;; CHECK-NEXT: ;; CHECK-NEXT: ;; CHECK-NEXT: General options: ;; CHECK-NEXT: ---------------- diff --git a/test/lit/help/wasm-emscripten-finalize.test b/test/lit/help/wasm-emscripten-finalize.test index 8666c2ea122..a4ba48b1608 100644 --- a/test/lit/help/wasm-emscripten-finalize.test +++ b/test/lit/help/wasm-emscripten-finalize.test @@ -161,6 +161,12 @@ ;; CHECK-NEXT: them and pass them back in, but not ;; CHECK-NEXT: inspect their contents or call them. ;; CHECK-NEXT: +;; CHECK-NEXT: --generate-stack-ir generate StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --optimize-stack-ir optimize StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --print-stack-ir print StackIR during writing +;; CHECK-NEXT: ;; CHECK-NEXT: ;; CHECK-NEXT: General options: ;; CHECK-NEXT: ---------------- diff --git a/test/lit/help/wasm-merge.test b/test/lit/help/wasm-merge.test index 997923256ef..c87be5edf1a 100644 --- a/test/lit/help/wasm-merge.test +++ b/test/lit/help/wasm-merge.test @@ -149,6 +149,12 @@ ;; CHECK-NEXT: them and pass them back in, but not ;; CHECK-NEXT: inspect their contents or call them. ;; CHECK-NEXT: +;; CHECK-NEXT: --generate-stack-ir generate StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --optimize-stack-ir optimize StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --print-stack-ir print StackIR during writing +;; CHECK-NEXT: ;; CHECK-NEXT: ;; CHECK-NEXT: General options: ;; CHECK-NEXT: ---------------- diff --git a/test/lit/help/wasm-metadce.test b/test/lit/help/wasm-metadce.test index 4d706dc0f1d..f0889eb81f7 100644 --- a/test/lit/help/wasm-metadce.test +++ b/test/lit/help/wasm-metadce.test @@ -174,6 +174,12 @@ ;; CHECK-NEXT: them and pass them back in, but not ;; CHECK-NEXT: inspect their contents or call them. ;; CHECK-NEXT: +;; CHECK-NEXT: --generate-stack-ir generate StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --optimize-stack-ir optimize StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --print-stack-ir print StackIR during writing +;; CHECK-NEXT: ;; CHECK-NEXT: ;; CHECK-NEXT: General options: ;; CHECK-NEXT: ---------------- diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test index f7ee47c09f6..4578e470e0a 100644 --- a/test/lit/help/wasm-opt.test +++ b/test/lit/help/wasm-opt.test @@ -53,6 +53,10 @@ ;; CHECK-NEXT: loads/stores/indirect calls when ;; CHECK-NEXT: fuzzing ;; CHECK-NEXT: +;; CHECK-NEXT: --no-fuzz-oob don't emit out-of-bounds +;; CHECK-NEXT: loads/stores/indirect calls when +;; CHECK-NEXT: fuzzing +;; CHECK-NEXT: ;; CHECK-NEXT: --emit-spec-wrapper,-esw Emit a wasm spec interpreter ;; CHECK-NEXT: wrapper file that can run the ;; CHECK-NEXT: wasm with some test values, @@ -182,8 +186,6 @@ ;; CHECK-NEXT: without JavaScript BigInt ;; CHECK-NEXT: support). ;; CHECK-NEXT: -;; CHECK-NEXT: --generate-stack-ir generate Stack IR -;; CHECK-NEXT: ;; CHECK-NEXT: --global-refining refine the types of globals ;; CHECK-NEXT: ;; CHECK-NEXT: --gsi globally optimize struct values @@ -333,8 +335,6 @@ ;; CHECK-NEXT: --optimize-j2cl optimizes J2CL specific ;; CHECK-NEXT: constructs. ;; CHECK-NEXT: -;; CHECK-NEXT: --optimize-stack-ir optimize Stack IR -;; CHECK-NEXT: ;; CHECK-NEXT: --outlining outline instructions ;; CHECK-NEXT: ;; CHECK-NEXT: --pick-load-signs pick load signs based on their @@ -369,9 +369,6 @@ ;; CHECK-NEXT: --print-minified print in minified s-expression ;; CHECK-NEXT: format ;; CHECK-NEXT: -;; CHECK-NEXT: --print-stack-ir print out Stack IR (useful for -;; CHECK-NEXT: internal debugging) -;; CHECK-NEXT: ;; CHECK-NEXT: --propagate-debug-locs propagate debug location from ;; CHECK-NEXT: parents or previous siblings to ;; CHECK-NEXT: child nodes @@ -746,6 +743,12 @@ ;; CHECK-NEXT: in, but not inspect their ;; CHECK-NEXT: contents or call them. ;; CHECK-NEXT: +;; CHECK-NEXT: --generate-stack-ir generate StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --optimize-stack-ir optimize StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --print-stack-ir print StackIR during writing +;; CHECK-NEXT: ;; CHECK-NEXT: ;; CHECK-NEXT: General options: ;; CHECK-NEXT: ---------------- diff --git a/test/lit/help/wasm-reduce.test b/test/lit/help/wasm-reduce.test index e28894e4acf..a98b8a1995b 100644 --- a/test/lit/help/wasm-reduce.test +++ b/test/lit/help/wasm-reduce.test @@ -155,6 +155,12 @@ ;; CHECK-NEXT: them and pass them back in, but not ;; CHECK-NEXT: inspect their contents or call them. ;; CHECK-NEXT: +;; CHECK-NEXT: --generate-stack-ir generate StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --optimize-stack-ir optimize StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --print-stack-ir print StackIR during writing +;; CHECK-NEXT: ;; CHECK-NEXT: ;; CHECK-NEXT: General options: ;; CHECK-NEXT: ---------------- diff --git a/test/lit/help/wasm-split.test b/test/lit/help/wasm-split.test index e7b287fcc01..fcd919ea88d 100644 --- a/test/lit/help/wasm-split.test +++ b/test/lit/help/wasm-split.test @@ -235,6 +235,12 @@ ;; CHECK-NEXT: them and pass them back in, but not ;; CHECK-NEXT: inspect their contents or call them. ;; CHECK-NEXT: +;; CHECK-NEXT: --generate-stack-ir generate StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --optimize-stack-ir optimize StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --print-stack-ir print StackIR during writing +;; CHECK-NEXT: ;; CHECK-NEXT: ;; CHECK-NEXT: General options: ;; CHECK-NEXT: ---------------- diff --git a/test/lit/help/wasm2js.test b/test/lit/help/wasm2js.test index 4b0330db6a1..13e93c33b92 100644 --- a/test/lit/help/wasm2js.test +++ b/test/lit/help/wasm2js.test @@ -132,8 +132,6 @@ ;; CHECK-NEXT: without JavaScript BigInt ;; CHECK-NEXT: support). ;; CHECK-NEXT: -;; CHECK-NEXT: --generate-stack-ir generate Stack IR -;; CHECK-NEXT: ;; CHECK-NEXT: --global-refining refine the types of globals ;; CHECK-NEXT: ;; CHECK-NEXT: --gsi globally optimize struct values @@ -283,8 +281,6 @@ ;; CHECK-NEXT: --optimize-j2cl optimizes J2CL specific ;; CHECK-NEXT: constructs. ;; CHECK-NEXT: -;; CHECK-NEXT: --optimize-stack-ir optimize Stack IR -;; CHECK-NEXT: ;; CHECK-NEXT: --outlining outline instructions ;; CHECK-NEXT: ;; CHECK-NEXT: --pick-load-signs pick load signs based on their @@ -319,9 +315,6 @@ ;; CHECK-NEXT: --print-minified print in minified s-expression ;; CHECK-NEXT: format ;; CHECK-NEXT: -;; CHECK-NEXT: --print-stack-ir print out Stack IR (useful for -;; CHECK-NEXT: internal debugging) -;; CHECK-NEXT: ;; CHECK-NEXT: --propagate-debug-locs propagate debug location from ;; CHECK-NEXT: parents or previous siblings to ;; CHECK-NEXT: child nodes @@ -696,6 +689,12 @@ ;; CHECK-NEXT: in, but not inspect their ;; CHECK-NEXT: contents or call them. ;; CHECK-NEXT: +;; CHECK-NEXT: --generate-stack-ir generate StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --optimize-stack-ir optimize StackIR during writing +;; CHECK-NEXT: +;; CHECK-NEXT: --print-stack-ir print StackIR during writing +;; CHECK-NEXT: ;; CHECK-NEXT: ;; CHECK-NEXT: General options: ;; CHECK-NEXT: ---------------- From f633cb4c75807f291ababeb62c06329e786981e8 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:02:07 -0700 Subject: [PATCH 14/77] test --- test/lit/passes/O.wast | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/lit/passes/O.wast b/test/lit/passes/O.wast index 7affbb8b7c9..baba79ee0c5 100644 --- a/test/lit/passes/O.wast +++ b/test/lit/passes/O.wast @@ -20,7 +20,7 @@ ;; CHECK: (export "end-if-else-call" (func $end-if-else-call)) - ;; CHECK: (func $ret (; has Stack IR ;) (result i32) + ;; CHECK: (func $ret (result i32) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (call $ret) ;; CHECK-NEXT: ) @@ -50,7 +50,7 @@ (unreachable) ) ) - ;; CHECK: (func $if-0-unreachable-to-none (; has Stack IR ;) (param $0 i64) + ;; CHECK: (func $if-0-unreachable-to-none (param $0 i64) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $if-0-unreachable-to-none (export "waka") (param $var$0 i64) @@ -68,7 +68,7 @@ ) ) ) - ;; CHECK: (func $many-selects (; has Stack IR ;) (param $0 i32) (result i32) + ;; CHECK: (func $many-selects (param $0 i32) (result i32) ;; CHECK-NEXT: (select ;; CHECK-NEXT: (i32.const -1073741824) ;; CHECK-NEXT: (select @@ -112,7 +112,7 @@ ) (local.get $0) ) - ;; CHECK: (func $end-if-else (; has Stack IR ;) (param $0 i32) (result i32) + ;; CHECK: (func $end-if-else (param $0 i32) (result i32) ;; CHECK-NEXT: (select ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (local.get $0) @@ -130,7 +130,7 @@ ) (local.get $x) ) - ;; CHECK: (func $end-if-else-call (; has Stack IR ;) (param $0 i32) (result i32) + ;; CHECK: (func $end-if-else-call (param $0 i32) (result i32) ;; CHECK-NEXT: (if (result i32) ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (then From db2a75bb0e2d7e90daa359963c6c56b4ab7bf1dc Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:02:21 -0700 Subject: [PATCH 15/77] test --- test/lit/passes/O3_Oz.wast | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lit/passes/O3_Oz.wast b/test/lit/passes/O3_Oz.wast index 48345663e65..cc129c964ce 100644 --- a/test/lit/passes/O3_Oz.wast +++ b/test/lit/passes/O3_Oz.wast @@ -14,7 +14,7 @@ ;; CHECK: (export "export" (func $export)) - ;; CHECK: (func $export (; has Stack IR ;) (param $0 i32) (result i32) + ;; CHECK: (func $export (param $0 i32) (result i32) ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.tee $0 ;; CHECK-NEXT: (i32.add From fbdd64ce4d493734dee7a40b222cc22f7f4699a9 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:02:32 -0700 Subject: [PATCH 16/77] test --- ...ith-loops_flexible-inline-max-function-size=30.wast | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/lit/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast b/test/lit/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast index 7037baf7d2d..830008e2fc6 100644 --- a/test/lit/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast +++ b/test/lit/passes/O3_inline-functions-with-loops_flexible-inline-max-function-size=30.wast @@ -22,7 +22,7 @@ ;; CHECK: (export "memory" (memory $memory)) - ;; CHECK: (func $fib (; has Stack IR ;) (param $0 i32) (result i32) + ;; CHECK: (func $fib (param $0 i32) (result i32) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.le_s ;; CHECK-NEXT: (local.get $0) @@ -76,7 +76,7 @@ ) ) ) - ;; CHECK: (func $looped (; has Stack IR ;) (param $0 i32) (result i32) + ;; CHECK: (func $looped (param $0 i32) (result i32) ;; CHECK-NEXT: (loop $L0 ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.ge_s @@ -123,7 +123,7 @@ ) ) - ;; CHECK: (func $t1 (; has Stack IR ;) (param $0 i32) (result i32) + ;; CHECK: (func $t1 (param $0 i32) (result i32) ;; CHECK-NEXT: (local.set $0 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.get $0) @@ -157,7 +157,7 @@ ) ) ) - ;; CHECK: (func $t2 (; has Stack IR ;) (param $0 i32) (result i32) + ;; CHECK: (func $t2 (param $0 i32) (result i32) ;; CHECK-NEXT: (call $fib ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -168,7 +168,7 @@ ) ) - ;; CHECK: (func $t3 (; has Stack IR ;) (param $0 i32) (result i32) + ;; CHECK: (func $t3 (param $0 i32) (result i32) ;; CHECK-NEXT: (call $fib ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.get $0) From dc0fd2da73a0b0755bbdce6aea6badcb28aa9c15 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:02:51 -0700 Subject: [PATCH 17/77] test --- test/lit/passes/O4_disable-bulk-memory.wast | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/lit/passes/O4_disable-bulk-memory.wast b/test/lit/passes/O4_disable-bulk-memory.wast index 0cafb1d5da5..d75258a9640 100644 --- a/test/lit/passes/O4_disable-bulk-memory.wast +++ b/test/lit/passes/O4_disable-bulk-memory.wast @@ -9,7 +9,7 @@ (global $global$0 (mut i32) (i32.const 10)) ;; CHECK: (export "func_59_invoker" (func $0)) (export "func_59_invoker" (func $0)) - ;; CHECK: (func $0 (; has Stack IR ;) + ;; CHECK: (func $0 ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $0 (; 0 ;) (type $0) @@ -226,7 +226,7 @@ ) (local.get $0) ) - ;; CHECK: (func $~lib/allocator/arena/__memory_allocate (; has Stack IR ;) (param $0 i32) (result i32) + ;; CHECK: (func $~lib/allocator/arena/__memory_allocate (param $0 i32) (result i32) ;; CHECK-NEXT: (local $1 i32) ;; CHECK-NEXT: (local $2 i32) ;; CHECK-NEXT: (local $3 i32) @@ -569,7 +569,7 @@ ) (local.get $0) ) - ;; CHECK: (func $assembly/index/Body#constructor (; has Stack IR ;) (param $0 f64) (param $1 f64) (param $2 f64) (param $3 f64) (param $4 f64) (param $5 f64) (param $6 f64) (result i32) + ;; CHECK: (func $assembly/index/Body#constructor (param $0 f64) (param $1 f64) (param $2 f64) (param $3 f64) (param $4 f64) (param $5 f64) (param $6 f64) (result i32) ;; CHECK-NEXT: (local $7 i32) ;; CHECK-NEXT: (f64.store ;; CHECK-NEXT: (local.tee $7 @@ -1299,7 +1299,7 @@ (local.get $5) ) ) - ;; CHECK: (func $assembly/index/init (; has Stack IR ;) + ;; CHECK: (func $assembly/index/init ;; CHECK-NEXT: (local $0 i32) ;; CHECK-NEXT: (local $1 i32) ;; CHECK-NEXT: (local $2 i32) @@ -1873,7 +1873,7 @@ ) ) ) - ;; CHECK: (func $assembly/index/NBodySystem#advance (; has Stack IR ;) (param $0 i32) + ;; CHECK: (func $assembly/index/NBodySystem#advance (param $0 i32) ;; CHECK-NEXT: (local $1 i32) ;; CHECK-NEXT: (local $2 f64) ;; CHECK-NEXT: (local $3 i32) @@ -2723,7 +2723,7 @@ ) (local.get $7) ) - ;; CHECK: (func $assembly/index/step (; has Stack IR ;) (result f64) + ;; CHECK: (func $assembly/index/step (result f64) ;; CHECK-NEXT: (local $0 f64) ;; CHECK-NEXT: (local $1 i32) ;; CHECK-NEXT: (local $2 i32) @@ -2933,7 +2933,7 @@ (global.get $global$5) ) ) - ;; CHECK: (func $assembly/index/bench (; has Stack IR ;) (param $0 i32) + ;; CHECK: (func $assembly/index/bench (param $0 i32) ;; CHECK-NEXT: (local $1 i32) ;; CHECK-NEXT: (block $label$1 ;; CHECK-NEXT: (loop $label$2 @@ -2985,7 +2985,7 @@ ) ) ) - ;; CHECK: (func $assembly/index/getBody (; has Stack IR ;) (param $0 i32) (result i32) + ;; CHECK: (func $assembly/index/getBody (param $0 i32) (result i32) ;; CHECK-NEXT: (local $1 i32) ;; CHECK-NEXT: (if (result i32) ;; CHECK-NEXT: (i32.lt_u @@ -3065,7 +3065,7 @@ ) ) ) - ;; CHECK: (func $start (; has Stack IR ;) + ;; CHECK: (func $start ;; CHECK-NEXT: (global.set $global$0 ;; CHECK-NEXT: (i32.const 104) ;; CHECK-NEXT: ) @@ -3076,7 +3076,7 @@ (func $start (; 26 ;) (type $0) (call $start:assembly/index) ) - ;; CHECK: (func $null (; has Stack IR ;) + ;; CHECK: (func $null ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $null (; 27 ;) (type $0) From e877cfa0d46aff18527d63da8b8294d18b505ec1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:03:04 -0700 Subject: [PATCH 18/77] test --- test/lit/passes/O_fast-math.wast | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/lit/passes/O_fast-math.wast b/test/lit/passes/O_fast-math.wast index 722f44a05c4..a964edc993f 100644 --- a/test/lit/passes/O_fast-math.wast +++ b/test/lit/passes/O_fast-math.wast @@ -37,7 +37,7 @@ ;; CHECK: (export "abs_sub_zero2" (func $abs_sub_zero2)) - ;; CHECK: (func $div (; has Stack IR ;) (result f32) + ;; CHECK: (func $div (result f32) ;; CHECK-NEXT: (f32.const -nan:0x23017a) ;; CHECK-NEXT: ) (func $div (export "div") (result f32) @@ -46,7 +46,7 @@ (f32.const 1) ) ) - ;; CHECK: (func $mul1 (; has Stack IR ;) (result f32) + ;; CHECK: (func $mul1 (result f32) ;; CHECK-NEXT: (f32.const -nan:0x34546d) ;; CHECK-NEXT: ) (func $mul1 (export "mul1") (result f32) @@ -55,7 +55,7 @@ (f32.const 1) ) ) - ;; CHECK: (func $mul2 (; has Stack IR ;) (result f32) + ;; CHECK: (func $mul2 (result f32) ;; CHECK-NEXT: (f32.const nan:0x400000) ;; CHECK-NEXT: ) (func $mul2 (export "mul2") (result f32) @@ -100,7 +100,7 @@ (f32.const -0) ) ) - ;; CHECK: (func $mul_neg_one1 (; has Stack IR ;) (param $0 f32) (result f32) + ;; CHECK: (func $mul_neg_one1 (param $0 f32) (result f32) ;; CHECK-NEXT: (f32.neg ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -111,7 +111,7 @@ (f32.const -1) ) ) - ;; CHECK: (func $mul_neg_one2 (; has Stack IR ;) (param $0 f64) (result f64) + ;; CHECK: (func $mul_neg_one2 (param $0 f64) (result f64) ;; CHECK-NEXT: (f64.neg ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -122,7 +122,7 @@ (f64.const -1) ) ) - ;; CHECK: (func $abs_sub_zero1 (; has Stack IR ;) (param $0 f32) (result f32) + ;; CHECK: (func $abs_sub_zero1 (param $0 f32) (result f32) ;; CHECK-NEXT: (f32.abs ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -136,7 +136,7 @@ ) ) ) - ;; CHECK: (func $abs_sub_zero2 (; has Stack IR ;) (param $0 f64) (result f64) + ;; CHECK: (func $abs_sub_zero2 (param $0 f64) (result f64) ;; CHECK-NEXT: (f64.abs ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) From d444b4b7862dc9dec82fcb16f0bd826917817f8d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:03:14 -0700 Subject: [PATCH 19/77] test --- test/lit/passes/Oz.wast | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/lit/passes/Oz.wast b/test/lit/passes/Oz.wast index 8c1db3083b7..eab5a95afd6 100644 --- a/test/lit/passes/Oz.wast +++ b/test/lit/passes/Oz.wast @@ -37,7 +37,7 @@ ;; CHECK: (export "precompute-simd" (func $precompute-simd)) - ;; CHECK: (func $basics (type $0) (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) + ;; CHECK: (func $basics (type $0) (param $0 i32) (param $1 i32) (result i32) ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.tee $0 ;; CHECK-NEXT: (i32.add @@ -59,7 +59,7 @@ ) (i32.add (local.get $x2) (local.get $y2)) ) - ;; CHECK: (func $8 (type $2) (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) + ;; CHECK: (func $8 (type $2) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) ;; CHECK-NEXT: (i32.store ;; CHECK-NEXT: (local.tee $0 ;; CHECK-NEXT: (i32.add @@ -131,7 +131,7 @@ ) ) - ;; CHECK: (func $9 (type $1) (; has Stack IR ;) (param $0 i32) (result i32) + ;; CHECK: (func $9 (type $1) (param $0 i32) (result i32) ;; CHECK-NEXT: (i32.mul ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const -4) @@ -147,7 +147,7 @@ ) ) - ;; CHECK: (func $10 (type $1) (; has Stack IR ;) (param $0 i32) (result i32) + ;; CHECK: (func $10 (type $1) (param $0 i32) (result i32) ;; CHECK-NEXT: (i32.shl ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const 31) @@ -163,7 +163,7 @@ ) ) - ;; CHECK: (func $11 (type $1) (; has Stack IR ;) (param $0 i32) (result i32) + ;; CHECK: (func $11 (type $1) (param $0 i32) (result i32) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (then @@ -201,7 +201,7 @@ ) (i32.const 0) ) - ;; CHECK: (func $12 (type $0) (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) + ;; CHECK: (func $12 (type $0) (param $0 i32) (param $1 i32) (result i32) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (then @@ -239,7 +239,7 @@ ) (i32.const 0) ) - ;; CHECK: (func $13 (type $0) (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) + ;; CHECK: (func $13 (type $0) (param $0 i32) (param $1 i32) (result i32) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (select ;; CHECK-NEXT: (local.get $1) @@ -268,7 +268,7 @@ (i32.const 0) ) - ;; CHECK: (func $14 (type $0) (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) + ;; CHECK: (func $14 (type $0) (param $0 i32) (param $1 i32) (result i32) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (select ;; CHECK-NEXT: (i32.const 0) @@ -297,7 +297,7 @@ (i32.const 0) ) - ;; CHECK: (func $precompute-simd (type $3) (; has Stack IR ;) (result v128) + ;; CHECK: (func $precompute-simd (type $3) (result v128) ;; CHECK-NEXT: (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000) ;; CHECK-NEXT: ) (func $precompute-simd (export "precompute-simd") (result v128) From 51a276c2189f83573aeee9d3827a054c1dc526fc Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:03:27 -0700 Subject: [PATCH 20/77] test --- ...asyncify_mod-asyncify-always-and-only-unwind_O.wast | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/lit/passes/asyncify_mod-asyncify-always-and-only-unwind_O.wast b/test/lit/passes/asyncify_mod-asyncify-always-and-only-unwind_O.wast index 99ac2c05f66..ec31a4118e7 100644 --- a/test/lit/passes/asyncify_mod-asyncify-always-and-only-unwind_O.wast +++ b/test/lit/passes/asyncify_mod-asyncify-always-and-only-unwind_O.wast @@ -42,7 +42,7 @@ ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - ;; CHECK: (func $calls-import (; has Stack IR ;) + ;; CHECK: (func $calls-import ;; CHECK-NEXT: (local $0 i32) ;; CHECK-NEXT: (call $import) ;; CHECK-NEXT: (i32.store @@ -76,7 +76,7 @@ (drop (i32.eqz (i32.const 17))) ) ) -;; CHECK: (func $asyncify_start_unwind (; has Stack IR ;) (param $0 i32) +;; CHECK: (func $asyncify_start_unwind (param $0 i32) ;; CHECK-NEXT: (global.set $__asyncify_state ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) @@ -98,7 +98,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) -;; CHECK: (func $asyncify_stop_unwind (; has Stack IR ;) +;; CHECK: (func $asyncify_stop_unwind ;; CHECK-NEXT: (global.set $__asyncify_state ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) @@ -117,7 +117,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) -;; CHECK: (func $asyncify_start_rewind (; has Stack IR ;) (param $0 i32) +;; CHECK: (func $asyncify_start_rewind (param $0 i32) ;; CHECK-NEXT: (global.set $__asyncify_state ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) @@ -139,6 +139,6 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) -;; CHECK: (func $asyncify_get_state (; has Stack IR ;) (result i32) +;; CHECK: (func $asyncify_get_state (result i32) ;; CHECK-NEXT: (global.get $__asyncify_state) ;; CHECK-NEXT: ) From 553268b203ca27bdd1e463da53130ecaaf88e821 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:03:42 -0700 Subject: [PATCH 21/77] test --- .../passes/asyncify_mod-asyncify-never-unwind_O.wast | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/lit/passes/asyncify_mod-asyncify-never-unwind_O.wast b/test/lit/passes/asyncify_mod-asyncify-never-unwind_O.wast index 38a54ea80e3..eefdabe3438 100644 --- a/test/lit/passes/asyncify_mod-asyncify-never-unwind_O.wast +++ b/test/lit/passes/asyncify_mod-asyncify-never-unwind_O.wast @@ -41,7 +41,7 @@ ;; CHECK: (export "asyncify_get_state" (func $asyncify_get_state)) - ;; CHECK: (func $calls-import (; has Stack IR ;) + ;; CHECK: (func $calls-import ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.or ;; CHECK-NEXT: (i32.eqz @@ -95,7 +95,7 @@ (drop (i32.eqz (i32.const 17))) ) ) -;; CHECK: (func $asyncify_start_unwind (; has Stack IR ;) (param $0 i32) +;; CHECK: (func $asyncify_start_unwind (param $0 i32) ;; CHECK-NEXT: (global.set $__asyncify_state ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) @@ -117,7 +117,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) -;; CHECK: (func $asyncify_stop_unwind (; has Stack IR ;) +;; CHECK: (func $asyncify_stop_unwind ;; CHECK-NEXT: (global.set $__asyncify_state ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) @@ -136,7 +136,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) -;; CHECK: (func $asyncify_start_rewind (; has Stack IR ;) (param $0 i32) +;; CHECK: (func $asyncify_start_rewind (param $0 i32) ;; CHECK-NEXT: (global.set $__asyncify_state ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) @@ -158,6 +158,6 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) -;; CHECK: (func $asyncify_get_state (; has Stack IR ;) (result i32) +;; CHECK: (func $asyncify_get_state (result i32) ;; CHECK-NEXT: (global.get $__asyncify_state) ;; CHECK-NEXT: ) From 80058f04cd8c9a52889274dea7426d748b19f0af Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:03:57 -0700 Subject: [PATCH 22/77] test --- test/lit/passes/flatten_dfo_O3_enable-threads.wast | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/lit/passes/flatten_dfo_O3_enable-threads.wast b/test/lit/passes/flatten_dfo_O3_enable-threads.wast index 34142b73f58..3e2dfb5395b 100644 --- a/test/lit/passes/flatten_dfo_O3_enable-threads.wast +++ b/test/lit/passes/flatten_dfo_O3_enable-threads.wast @@ -28,7 +28,7 @@ ;; CHECK: (export "dfo-tee-get" (func $dfo-tee-get)) - ;; CHECK: (func $one (; has Stack IR ;) + ;; CHECK: (func $one ;; CHECK-NEXT: (block $label$3 ;; CHECK-NEXT: (br_if $label$3 ;; CHECK-NEXT: (i32.load @@ -56,7 +56,7 @@ ) (unreachable) ) - ;; CHECK: (func $two (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) + ;; CHECK: (func $two (param $0 i32) (param $1 i32) (result i32) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) (func $two (export "two") (param $var$0 i32) (param $var$1 i32) (result i32) @@ -110,7 +110,7 @@ (nop) (i32.const 0) ) - ;; CHECK: (func $use-var (; has Stack IR ;) (param $0 i64) (param $1 i32) (result f64) + ;; CHECK: (func $use-var (param $0 i64) (param $1 i32) (result f64) ;; CHECK-NEXT: (loop $label$8 ;; CHECK-NEXT: (br_if $label$8 ;; CHECK-NEXT: (local.get $1) @@ -184,7 +184,7 @@ ) (unreachable) ) - ;; CHECK: (func $bad1 (; has Stack IR ;) + ;; CHECK: (func $bad1 ;; CHECK-NEXT: (i32.store ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (i32.const -16384) @@ -236,7 +236,7 @@ ) ) ) - ;; CHECK: (func $only-dfo (; has Stack IR ;) (param $0 f64) (result f64) + ;; CHECK: (func $only-dfo (param $0 f64) (result f64) ;; CHECK-NEXT: (local $1 i32) ;; CHECK-NEXT: (loop $label$1 ;; CHECK-NEXT: (br $label$1) @@ -270,7 +270,7 @@ (br $label$1) ) ) - ;; CHECK: (func $dfo-tee-get (; has Stack IR ;) (result i32) + ;; CHECK: (func $dfo-tee-get (result i32) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) (func $dfo-tee-get (export "dfo-tee-get") (result i32) From 5cfafca5d2debd1e1fc8d9c0485192f69f43c40b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:04:11 -0700 Subject: [PATCH 23/77] test --- .../flatten_simplify-locals-nonesting_dfo_O3.wast | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/lit/passes/flatten_simplify-locals-nonesting_dfo_O3.wast b/test/lit/passes/flatten_simplify-locals-nonesting_dfo_O3.wast index 142fabeea14..2c033e0fe2c 100644 --- a/test/lit/passes/flatten_simplify-locals-nonesting_dfo_O3.wast +++ b/test/lit/passes/flatten_simplify-locals-nonesting_dfo_O3.wast @@ -25,7 +25,7 @@ ;; CHECK: (export "only-dfo" (func $only-dfo)) - ;; CHECK: (func $if-select (; has Stack IR ;) + ;; CHECK: (func $if-select ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $if-select (export "if-select") @@ -47,7 +47,7 @@ ) ) ) - ;; CHECK: (func $unreachable-body-update-zext (; has Stack IR ;) (result f64) + ;; CHECK: (func $unreachable-body-update-zext (result f64) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $unreachable-body-update-zext (export "unreachable-body-update-zext") (result f64) @@ -61,7 +61,7 @@ ) (f64.const -9223372036854775808) ) - ;; CHECK: (func $ssa-const (; has Stack IR ;) (param $0 i32) (param $1 f64) (param $2 f64) (result i32) + ;; CHECK: (func $ssa-const (param $0 i32) (param $1 f64) (param $2 f64) (result i32) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $ssa-const (export "ssa-const") (param $var$0 i32) (param $var$1 f64) (param $var$2 f64) (result i32) @@ -99,7 +99,7 @@ ) ) ) - ;; CHECK: (func $if-nothing (; has Stack IR ;) (param $0 i64) + ;; CHECK: (func $if-nothing (param $0 i64) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $if-nothing (export "if-nothing") (param $var$0 i64) @@ -130,7 +130,7 @@ (unreachable) ) ) - ;; CHECK: (func $only-dfo (; has Stack IR ;) (param $0 f64) (result i32) + ;; CHECK: (func $only-dfo (param $0 f64) (result i32) ;; CHECK-NEXT: (local $1 i32) ;; CHECK-NEXT: (loop $label$1 ;; CHECK-NEXT: (if From a7206df825dfe2d570d4e9f0bd80987d5b4d56af Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:04:22 -0700 Subject: [PATCH 24/77] test --- test/lit/passes/global-effects-O.wast | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/lit/passes/global-effects-O.wast b/test/lit/passes/global-effects-O.wast index c24159eace4..c7ba0678186 100644 --- a/test/lit/passes/global-effects-O.wast +++ b/test/lit/passes/global-effects-O.wast @@ -56,13 +56,13 @@ ;; CHECK_1: (func $main (type $0) ;; CHECK_1-NEXT: (nop) ;; CHECK_1-NEXT: ) - ;; CHECK_3: (func $main (type $0) (; has Stack IR ;) + ;; CHECK_3: (func $main (type $0) ;; CHECK_3-NEXT: (nop) ;; CHECK_3-NEXT: ) - ;; CHECK_s: (func $main (type $0) (; has Stack IR ;) + ;; CHECK_s: (func $main (type $0) ;; CHECK_s-NEXT: (nop) ;; CHECK_s-NEXT: ) - ;; CHECK_O: (func $main (type $0) (; has Stack IR ;) + ;; CHECK_O: (func $main (type $0) ;; CHECK_O-NEXT: (nop) ;; CHECK_O-NEXT: ) (func $main @@ -119,7 +119,7 @@ ;; CHECK_1-NEXT: (local.get $0) ;; CHECK_1-NEXT: ) ;; CHECK_1-NEXT: ) - ;; CHECK_3: (func $pointless-work (type $1) (; has Stack IR ;) (result i32) + ;; CHECK_3: (func $pointless-work (type $1) (result i32) ;; CHECK_3-NEXT: (local $0 i32) ;; CHECK_3-NEXT: (loop $loop (result i32) ;; CHECK_3-NEXT: (br_if $loop @@ -136,7 +136,7 @@ ;; CHECK_3-NEXT: (local.get $0) ;; CHECK_3-NEXT: ) ;; CHECK_3-NEXT: ) - ;; CHECK_s: (func $pointless-work (type $1) (; has Stack IR ;) (result i32) + ;; CHECK_s: (func $pointless-work (type $1) (result i32) ;; CHECK_s-NEXT: (local $0 i32) ;; CHECK_s-NEXT: (loop $loop (result i32) ;; CHECK_s-NEXT: (br_if $loop @@ -153,7 +153,7 @@ ;; CHECK_s-NEXT: (local.get $0) ;; CHECK_s-NEXT: ) ;; CHECK_s-NEXT: ) - ;; CHECK_O: (func $pointless-work (type $1) (; has Stack IR ;) (result i32) + ;; CHECK_O: (func $pointless-work (type $1) (result i32) ;; CHECK_O-NEXT: (local $0 i32) ;; CHECK_O-NEXT: (loop $loop (result i32) ;; CHECK_O-NEXT: (br_if $loop From 46b1cab3cf2c66940d5afb1bf9cad1f04df43ca7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:04:31 -0700 Subject: [PATCH 25/77] test --- test/lit/passes/gto_and_cfp_in_O.wast | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/lit/passes/gto_and_cfp_in_O.wast b/test/lit/passes/gto_and_cfp_in_O.wast index a723038eb2f..b1e9a47df50 100644 --- a/test/lit/passes/gto_and_cfp_in_O.wast +++ b/test/lit/passes/gto_and_cfp_in_O.wast @@ -26,7 +26,7 @@ ;; OPEN_WORLD: (export "main" (func $main)) - ;; OPEN_WORLD: (func $by-ref (type $1) (; has Stack IR ;) + ;; OPEN_WORLD: (func $by-ref (type $1) ;; OPEN_WORLD-NEXT: (struct.set $struct 1 ;; OPEN_WORLD-NEXT: (global.get $glob) ;; OPEN_WORLD-NEXT: (i32.const 200) @@ -49,10 +49,10 @@ ;; CHECK: (export "main" (func $main)) - ;; CHECK: (func $main (type $0) (; has Stack IR ;) (result i32) + ;; CHECK: (func $main (type $0) (result i32) ;; CHECK-NEXT: (i32.const 100) ;; CHECK-NEXT: ) - ;; OPEN_WORLD: (func $main (type $2) (; has Stack IR ;) (result i32) + ;; OPEN_WORLD: (func $main (type $2) (result i32) ;; OPEN_WORLD-NEXT: (struct.get $struct 1 ;; OPEN_WORLD-NEXT: (global.get $glob) ;; OPEN_WORLD-NEXT: ) From efc2e8fcbfa20739f8dfeb2fd2089f98e6fdc32a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:05:14 -0700 Subject: [PATCH 26/77] test --- test/lit/passes/type-ssa_and_merging.wast | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/lit/passes/type-ssa_and_merging.wast b/test/lit/passes/type-ssa_and_merging.wast index 670de31ac45..8928820bfcd 100644 --- a/test/lit/passes/type-ssa_and_merging.wast +++ b/test/lit/passes/type-ssa_and_merging.wast @@ -33,7 +33,7 @@ ;; NOP: (export "main2" (func $main2)) - ;; NOP: (func $main1 (type $2) (; has Stack IR ;) (result i32) + ;; NOP: (func $main1 (type $2) (result i32) ;; NOP-NEXT: (call $get-a-1 ;; NOP-NEXT: (struct.new $A ;; NOP-NEXT: (i32.const 42) @@ -57,7 +57,7 @@ ) ) - ;; NOP: (func $main2 (type $2) (; has Stack IR ;) (result i32) + ;; NOP: (func $main2 (type $2) (result i32) ;; NOP-NEXT: (call $get-a-2 ;; NOP-NEXT: (struct.new $A ;; NOP-NEXT: (i32.const 1337) @@ -77,7 +77,7 @@ ) ) - ;; NOP: (func $get-a-1 (type $0) (; has Stack IR ;) (param $0 (ref $A)) (result i32) + ;; NOP: (func $get-a-1 (type $0) (param $0 (ref $A)) (result i32) ;; NOP-NEXT: (if ;; NOP-NEXT: (call $import) ;; NOP-NEXT: (then @@ -119,7 +119,7 @@ (struct.get $A 0 (local.get 0)) ) - ;; NOP: (func $get-a-2 (type $0) (; has Stack IR ;) (param $0 (ref $A)) (result i32) + ;; NOP: (func $get-a-2 (type $0) (param $0 (ref $A)) (result i32) ;; NOP-NEXT: (if ;; NOP-NEXT: (call $import) ;; NOP-NEXT: (then From 58a15727013de1d472e9b503baeb49c661a6fbde Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:05:29 -0700 Subject: [PATCH 27/77] test --- test/passes/O.bin.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/passes/O.bin.txt b/test/passes/O.bin.txt index d35a4d11c64..3302ebcc710 100644 --- a/test/passes/O.bin.txt +++ b/test/passes/O.bin.txt @@ -5,7 +5,7 @@ (export "fac-iter" (func $2)) (export "fac-iter-named" (func $3)) (export "fac-opt" (func $4)) - (func $0 (; has Stack IR ;) (param $0 i64) (result i64) + (func $0 (param $0 i64) (result i64) (if (result i64) (i64.eqz (local.get $0) @@ -26,7 +26,7 @@ ) ) ) - (func $1 (; has Stack IR ;) (param $0 i64) (result i64) + (func $1 (param $0 i64) (result i64) (if (result i64) (i64.eqz (local.get $0) @@ -47,10 +47,10 @@ ) ) ) - (func $2 (; has Stack IR ;) (param $0 i64) (result i64) + (func $2 (param $0 i64) (result i64) (unreachable) ) - (func $3 (; has Stack IR ;) (param $0 i64) (result i64) + (func $3 (param $0 i64) (result i64) (local $1 i64) (local.set $1 (i64.const 1) @@ -81,7 +81,7 @@ ) (local.get $1) ) - (func $4 (; has Stack IR ;) (param $0 i64) (result i64) + (func $4 (param $0 i64) (result i64) (local $1 i64) (local.set $1 (i64.const 1) From b2fee9ef62c104f1c85f60c19c61f16d353a47fa Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:05:46 -0700 Subject: [PATCH 28/77] test --- test/passes/O3_low-memory-unused_metrics.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/passes/O3_low-memory-unused_metrics.txt b/test/passes/O3_low-memory-unused_metrics.txt index 547eb1673ed..fd9245adc2a 100644 --- a/test/passes/O3_low-memory-unused_metrics.txt +++ b/test/passes/O3_low-memory-unused_metrics.txt @@ -42,7 +42,7 @@ total (import "env" "memset" (func $fimport$97 (param i32 i32 i32) (result i32))) (import "env" "memcpy" (func $fimport$98 (param i32 i32 i32) (result i32))) (export "deflate" (func $0)) - (func $0 (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) + (func $0 (param $0 i32) (param $1 i32) (result i32) (local $2 i32) (local $3 i32) (local $4 i32) From 2666b6265ecfd49879712427c01b43d1e08d24ec Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:06:09 -0700 Subject: [PATCH 29/77] test --- test/passes/Oz_fuzz-exec_all-features.txt | 32 +++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/passes/Oz_fuzz-exec_all-features.txt b/test/passes/Oz_fuzz-exec_all-features.txt index c46085be11c..b69b9728cca 100644 --- a/test/passes/Oz_fuzz-exec_all-features.txt +++ b/test/passes/Oz_fuzz-exec_all-features.txt @@ -81,7 +81,7 @@ (export "static-casts" (func $static-casts)) (export "static-br_on_cast" (func $br_on_cast)) (export "static-br_on_cast_fail" (func $static-br_on_cast_fail)) - (func $structs (type $void_func) (; has Stack IR ;) + (func $structs (type $void_func) (local $0 i32) (call $log (i32.const 0) @@ -98,7 +98,7 @@ (i32.const 100) ) ) - (func $arrays (type $void_func) (; has Stack IR ;) + (func $arrays (type $void_func) (local $0 (ref $bytes)) (local.set $0 (array.new $bytes @@ -139,12 +139,12 @@ ) ) ) - (func $br_on_cast (type $void_func) (; has Stack IR ;) + (func $br_on_cast (type $void_func) (call $log (i32.const 3) ) ) - (func $br_on_failed_cast-1 (type $void_func) (; has Stack IR ;) + (func $br_on_failed_cast-1 (type $void_func) (local $0 (ref $struct)) (local.set $0 (struct.new_default $struct) @@ -166,7 +166,7 @@ ) ) ) - (func $br_on_failed_cast-2 (type $void_func) (; has Stack IR ;) + (func $br_on_failed_cast-2 (type $void_func) (call $log (i32.const 1) ) @@ -174,15 +174,15 @@ (i32.const 999) ) ) - (func $cast-null-anyref-to-gc (type $void_func) (; has Stack IR ;) + (func $cast-null-anyref-to-gc (type $void_func) (call $log (i32.const 0) ) ) - (func $br-on_non_null (type $void_func) (; has Stack IR ;) + (func $br-on_non_null (type $void_func) (nop) ) - (func $br-on_non_null-2 (type $void_func) (; has Stack IR ;) + (func $br-on_non_null-2 (type $void_func) (drop (block (call $log @@ -192,7 +192,7 @@ ) ) ) - (func $cast-on-func (type $void_func) (; has Stack IR ;) + (func $cast-on-func (type $void_func) (call $log (i32.const 0) ) @@ -204,7 +204,7 @@ ) (unreachable) ) - (func $init-array-packed (type $int_func) (; has Stack IR ;) (result i32) + (func $init-array-packed (type $int_func) (result i32) (array.get_u $bytes (array.new $bytes (i32.const -43) @@ -213,7 +213,7 @@ (i32.const 10) ) ) - (func $array-copy (type $void_func) (; has Stack IR ;) + (func $array-copy (type $void_func) (local $0 (ref $bytes)) (local $1 (ref $bytes)) (array.set $bytes @@ -268,7 +268,7 @@ ) ) ) - (func $array.new_fixed (type $void_func) (; has Stack IR ;) + (func $array.new_fixed (type $void_func) (local $0 i32) (local $1 i32) (local.set $0 @@ -287,12 +287,12 @@ (i32.const 50) ) ) - (func $array.new_fixed-packed (type $void_func) (; has Stack IR ;) + (func $array.new_fixed-packed (type $void_func) (call $log (i32.const 8) ) ) - (func $static-casts (type $void_func) (; has Stack IR ;) + (func $static-casts (type $void_func) (call $log (i32.const 1) ) @@ -312,7 +312,7 @@ (i32.const 1) ) ) - (func $static-br_on_cast_fail (type $void_func) (; has Stack IR ;) + (func $static-br_on_cast_fail (type $void_func) (call $log (i32.const -2) ) @@ -380,7 +380,7 @@ ignoring comparison of ExecutionResults! (module (type $0 (func (result i32))) (export "foo" (func $foo)) - (func $foo (type $0) (; has Stack IR ;) (result i32) + (func $foo (type $0) (result i32) (i32.const 0) ) ) From c423f0556aa1d65942d74aa9a567a2bc574c7e05 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:06:25 -0700 Subject: [PATCH 30/77] test --- test/passes/converge_O3_metrics.bin.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/passes/converge_O3_metrics.bin.txt b/test/passes/converge_O3_metrics.bin.txt index bd977b342de..7b077ceb415 100644 --- a/test/passes/converge_O3_metrics.bin.txt +++ b/test/passes/converge_O3_metrics.bin.txt @@ -46,13 +46,13 @@ total (elem $0 (i32.const 0) $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $___stdout_write $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE6xsputnEPKci $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE8overflowEi) (export "_main" (func $_main)) (export "_malloc" (func $_malloc)) - (func $b0 (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (result i32) + (func $b0 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (result i32) (i32.const 0) ) - (func $_malloc (; has Stack IR ;) (param $0 i32) (result i32) + (func $_malloc (param $0 i32) (result i32) (i32.const 0) ) - (func $_main (; has Stack IR ;) (result i32) + (func $_main (result i32) (local $0 i32) (local $1 i32) (local.set $0 @@ -157,7 +157,7 @@ total ) (i32.const 0) ) - (func $___stdout_write (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $___stdout_write (param $0 i32) (param $1 i32) (param $2 i32) (result i32) (global.set $global$0 (i32.const 32) ) @@ -187,7 +187,7 @@ total ) (i32.const 1) ) - (func $__ZNSt3__211__stdoutbufIcE8overflowEi (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) + (func $__ZNSt3__211__stdoutbufIcE8overflowEi (param $0 i32) (param $1 i32) (result i32) (i32.store8 (i32.const 0) (local.get $1) @@ -212,7 +212,7 @@ total ) (i32.const 0) ) - (func $__ZNSt3__211__stdoutbufIcE6xsputnEPKci (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $__ZNSt3__211__stdoutbufIcE6xsputnEPKci (param $0 i32) (param $1 i32) (param $2 i32) (result i32) (drop (call_indirect (type $0) (i32.const 0) From 59363026ec77a5e8298a6a5caf4f277f0d3ca9b7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:06:37 -0700 Subject: [PATCH 31/77] test --- test/passes/fuzz-exec_O.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/passes/fuzz-exec_O.txt b/test/passes/fuzz-exec_O.txt index 7bdf8d252d1..d636cc765ea 100644 --- a/test/passes/fuzz-exec_O.txt +++ b/test/passes/fuzz-exec_O.txt @@ -8,7 +8,7 @@ (memory $0 1 1) (export "func_0" (func $func_0)) (export "func_1" (func $func_1)) - (func $func_0 (; has Stack IR ;) (result i64) + (func $func_0 (result i64) (block $label$0 (result i64) (br_if $label$0 (i64.const 1234) @@ -18,7 +18,7 @@ ) ) ) - (func $func_1 (; has Stack IR ;) (result i32) + (func $func_1 (result i32) (i32.load16_s offset=22 align=1 (i32.const -1) ) @@ -59,7 +59,7 @@ (export "add4" (func $div)) (export "sub1" (func $div)) (export "sub2" (func $div)) - (func $div (; has Stack IR ;) (result f32) + (func $div (result f32) (f32.const nan:0x400000) ) ) From d16d78584913ca0d6ac7bd49ef0d900d2f430954 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:14:08 -0700 Subject: [PATCH 32/77] fix --- src/passes/pass.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index 0d8002f8592..c5a2bcc55e2 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -907,6 +907,7 @@ void PassRunner::runPass(Pass* pass) { assert(!pass->getPassRunner()); pass->setPassRunner(this); pass->run(wasm); + handleAfterEffects(pass); } void PassRunner::runPassOnFunction(Pass* pass, Function* func) { From 8ad87898fd7179645893ae5fdc8778e68c2998da Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:14:28 -0700 Subject: [PATCH 33/77] test --- test/example/relooper-fuzz.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/example/relooper-fuzz.txt b/test/example/relooper-fuzz.txt index 1030fac320d..e4c3f6db4ce 100644 --- a/test/example/relooper-fuzz.txt +++ b/test/example/relooper-fuzz.txt @@ -311,7 +311,7 @@ (memory $0 1 1) (export "mem" (memory $0)) (start $main) - (func $check (; has Stack IR ;) (result i32) + (func $check (result i32) (if (i32.eq (i32.load @@ -348,7 +348,7 @@ ) ) ) - (func $main (; has Stack IR ;) + (func $main (local $0 i32) (local $1 i32) (i32.store From 9de37cd3bfaea7e631e9c37eacc40c8d5023dd49 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:14:34 -0700 Subject: [PATCH 34/77] test --- test/example/relooper-fuzz1.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/example/relooper-fuzz1.txt b/test/example/relooper-fuzz1.txt index 3cdb12e69f1..675d5104260 100644 --- a/test/example/relooper-fuzz1.txt +++ b/test/example/relooper-fuzz1.txt @@ -293,7 +293,7 @@ (memory $0 1 1) (export "mem" (memory $0)) (start $main) - (func $check (; has Stack IR ;) (result i32) + (func $check (result i32) (if (i32.eq (i32.load @@ -330,7 +330,7 @@ ) ) ) - (func $main (; has Stack IR ;) + (func $main (local $0 i32) (i32.store (i32.const 8) From acc77b96dc5a102009801ed4b6c607ac56f7852d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:29:59 -0700 Subject: [PATCH 35/77] fix --- src/tools/tool-options.h | 6 +++--- src/tools/wasm-opt.cpp | 26 ++++++++++++++++++-------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h index 648f501a796..fd98e50491c 100644 --- a/src/tools/tool-options.h +++ b/src/tools/tool-options.h @@ -157,19 +157,19 @@ struct ToolOptions : public Options { "generate StackIR during writing", ToolOptionsCategory, Options::Arguments::Zero, - [&](Options* o, const std::string& arguments) { passOptions.generateStackIR = false; }) + [&](Options* o, const std::string& arguments) { passOptions.generateStackIR = true; }) .add("--optimize-stack-ir", "", "optimize StackIR during writing", ToolOptionsCategory, Options::Arguments::Zero, - [&](Options* o, const std::string& arguments) { passOptions.optimizeStackIR = false; }) + [&](Options* o, const std::string& arguments) { passOptions.generateStackIR = true; passOptions.optimizeStackIR = true; }) .add("--print-stack-ir", "", "print StackIR during writing", ToolOptionsCategory, Options::Arguments::Zero, - [&](Options* o, const std::string& arguments) { passOptions.printStackIR = false; }) + [&](Options* o, const std::string& arguments) { passOptions.generateStackIR = true; passOptions.printStackIR = true; }) ; } diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index 3d6127feab1..447927c6e17 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -365,6 +365,14 @@ int main(int argc, const char* argv[]) { bool translateToNewEH = wasm.features.hasExceptionHandling() && experimentalNewEH; + // Write the binary to an unused buffer and return the size. + auto computeBinarySize = [&]() { + BufferWithRandomAccess buffer; + WasmBinaryWriter writer(&wasm, buffer, options.passOptions); + writer.write(); + return buffer.size(); + }; + if (!options.runningPasses()) { if (!options.quiet && !translateToNewEH) { std::cerr << "warning: no passes specified, not doing any work\n"; @@ -384,17 +392,11 @@ int main(int argc, const char* argv[]) { if (converge) { // Keep on running passes to convergence, defined as binary // size no longer decreasing. - auto getSize = [&]() { - BufferWithRandomAccess buffer; - WasmBinaryWriter writer(&wasm, buffer, options.passOptions); - writer.write(); - return buffer.size(); - }; - auto lastSize = getSize(); + auto lastSize = computeBinarySize(); while (1) { BYN_TRACE("running iteration for convergence (" << lastSize << ")..\n"); runPasses(); - auto currSize = getSize(); + auto currSize = computeBinarySize(); if (currSize >= lastSize) { break; } @@ -423,6 +425,14 @@ int main(int argc, const char* argv[]) { } if (options.extra.count("output") == 0) { + if (options.passOptions.printStackIR) { + // The user asked to print StackIR without setting an output file, so we + // are not emitting a binary, but we do want to go through the binary + // writing process just to get StackIR to emit here. We can do that by + // computing the binary size. + computeBinarySize(); + return 0; + } if (!options.quiet) { std::cerr << "warning: no output file specified, not emitting output\n"; } From 78ee7fd197fdc4345f8cfe8b0d1b79a3499b5d59 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:55:06 -0700 Subject: [PATCH 36/77] builds --- src/wasm-binary.h | 1 + src/wasm/wasm-binary.cpp | 56 +- test/lit/passes/optimize-stack-ir.wast | 1308 ++++++++++------ test/lit/passes/stack-ir-eh.wast | 41 +- test/lit/passes/stack-ir-non-nullable.wast | 762 +++++---- test/lit/passes/translate-to-new-eh.wast | 1380 ++++++++++------- test/passes/O1_print-stack-ir.txt | 31 +- ...O2_precompute-propagate_print-stack-ir.txt | 8 +- test/passes/O2_print-stack-ir.txt | 34 +- test/passes/O3_print-stack-ir.txt | 30 +- ...print-stack-ir_all-features_disable-gc.txt | 30 +- ...d-brs_generate-stack-ir_print-stack-ir.txt | 34 +- 12 files changed, 2302 insertions(+), 1413 deletions(-) diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 310b251c177..4ec7e335249 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1314,6 +1314,7 @@ class WasmBinaryWriter { void writeFunctionSignatures(); void writeExpression(Expression* curr); + void prepareFunctions(); void writeFunctions(); void writeStrings(); void writeGlobals(); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 86bf846c511..811366f99a7 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -69,6 +69,7 @@ void WasmBinaryWriter::write() { writeStart(); writeElementSegments(); writeDataCount(); + prepareFunctions(); writeFunctions(); writeDataSegments(); if (debugInfo || emitModuleName) { @@ -370,6 +371,42 @@ void WasmBinaryWriter::writeImports() { finishSection(start); } +void WasmBinaryWriter::prepareFunctions() { + if (!options.generateStackIR) { + return; + } + + // Generate StackIR for functions in parallel, and optimize if requested. + struct StackIRPass + : public WalkerPass> { + bool isFunctionParallel() override { return true; } + + std::unique_ptr create() override { + return std::make_unique(); + } + + void doWalkFunction(Function* func) { + StackIRGenerator stackIRGen(*getModule(), func); + stackIRGen.write(); + func->stackIR = std::make_unique(); + func->stackIR->swap(stackIRGen.getStackIR()); + + auto& options = getPassOptions(); + if (options.optimizeStackIR) { + StackIROptimizer optimizer(func, options, getModule()->features); + optimizer.run(); + } + } + }; + + PassRunner runner(wasm, options); + StackIRPass().run(&runner, wasm); + + if (options.printStackIR) { + printStackIR(std::cout, wasm); + } +} + void WasmBinaryWriter::writeFunctionSignatures() { if (importInfo->getNumDefinedFunctions() == 0) { return; @@ -403,24 +440,7 @@ void WasmBinaryWriter::writeFunctions() { size_t sizePos = writeU32LEBPlaceholder(); size_t start = o.size(); BYN_TRACE("writing" << func->name << std::endl); - - if (options.generateStackIR) { - StackIRGenerator stackIRGen(*getModule(), func); - stackIRGen.write(); - func->stackIR = std::make_unique(); - func->stackIR->swap(stackIRGen.getStackIR()); - - if (options.optimizeStackIR) { - StackIROptimizer optimizer(func, options, wasm->features); - optimizer.run(); - } - - if (options.printStackIR) { // from a wasm-opt commandline flag - printStackIR(std::cout, wasm); - } - } - - // Emit Stack IR if present, and if we can + // Emit Stack IR if present. if (func->stackIR) { BYN_TRACE("write Stack IR\n"); StackIRToBinaryWriter writer(*this, o, func, sourceMap, DWARF); diff --git a/test/lit/passes/optimize-stack-ir.wast b/test/lit/passes/optimize-stack-ir.wast index 123be3afb8a..bd744524ed2 100644 --- a/test/lit/passes/optimize-stack-ir.wast +++ b/test/lit/passes/optimize-stack-ir.wast @@ -91,39 +91,59 @@ ;; CHECK: (func $importedDoubles (type $4) (result f64) ;; CHECK-NEXT: (local $temp f64) - ;; CHECK-NEXT: block $topmost (result f64) - ;; CHECK-NEXT: i32.const 8 - ;; CHECK-NEXT: f64.load - ;; CHECK-NEXT: i32.const 16 - ;; CHECK-NEXT: f64.load - ;; CHECK-NEXT: f64.add - ;; CHECK-NEXT: i32.const 16 - ;; CHECK-NEXT: f64.load - ;; CHECK-NEXT: f64.neg - ;; CHECK-NEXT: f64.add - ;; CHECK-NEXT: i32.const 8 - ;; CHECK-NEXT: f64.load - ;; CHECK-NEXT: f64.neg - ;; CHECK-NEXT: f64.add - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: i32.const 24 - ;; CHECK-NEXT: i32.load - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: i32.gt_s - ;; CHECK-NEXT: if - ;; CHECK-NEXT: f64.const -3.4 - ;; CHECK-NEXT: br $topmost - ;; CHECK-NEXT: end - ;; CHECK-NEXT: i32.const 32 - ;; CHECK-NEXT: f64.load - ;; CHECK-NEXT: f64.const 0 - ;; CHECK-NEXT: f64.gt - ;; CHECK-NEXT: if - ;; CHECK-NEXT: f64.const 5.6 - ;; CHECK-NEXT: br $topmost - ;; CHECK-NEXT: end - ;; CHECK-NEXT: f64.const 1.2 - ;; CHECK-NEXT: end + ;; CHECK-NEXT: (block $topmost (result f64) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (f64.add + ;; CHECK-NEXT: (f64.add + ;; CHECK-NEXT: (f64.add + ;; CHECK-NEXT: (f64.load + ;; CHECK-NEXT: (i32.const 8) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (f64.load + ;; CHECK-NEXT: (i32.const 16) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (f64.neg + ;; CHECK-NEXT: (f64.load + ;; CHECK-NEXT: (i32.const 16) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (f64.neg + ;; CHECK-NEXT: (f64.load + ;; CHECK-NEXT: (i32.const 8) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (i32.load + ;; CHECK-NEXT: (i32.const 24) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (br $topmost + ;; CHECK-NEXT: (f64.const -3.4) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (f64.gt + ;; CHECK-NEXT: (f64.load + ;; CHECK-NEXT: (i32.const 32) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (f64.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (br $topmost + ;; CHECK-NEXT: (f64.const 5.6) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (f64.const 1.2) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $importedDoubles (type $4) (result f64) (local $temp f64) @@ -186,37 +206,53 @@ ;; CHECK-NEXT: (local $t f64) ;; CHECK-NEXT: (local $Int f64) ;; CHECK-NEXT: (local $Double i32) - ;; CHECK-NEXT: block $topmost (result f64) - ;; CHECK-NEXT: local.get $x - ;; CHECK-NEXT: f64.const 0 - ;; CHECK-NEXT: f64.gt - ;; CHECK-NEXT: if - ;; CHECK-NEXT: f64.const 1.2 - ;; CHECK-NEXT: br $topmost - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $Int - ;; CHECK-NEXT: f64.const 0 - ;; CHECK-NEXT: f64.gt - ;; CHECK-NEXT: if - ;; CHECK-NEXT: f64.const -3.4 - ;; CHECK-NEXT: br $topmost - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $Double - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: i32.gt_s - ;; CHECK-NEXT: if - ;; CHECK-NEXT: f64.const 5.6 - ;; CHECK-NEXT: br $topmost - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $x - ;; CHECK-NEXT: local.get $y - ;; CHECK-NEXT: f64.lt - ;; CHECK-NEXT: if - ;; CHECK-NEXT: local.get $x - ;; CHECK-NEXT: br $topmost - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $y - ;; CHECK-NEXT: end + ;; CHECK-NEXT: (block $topmost (result f64) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (f64.gt + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (f64.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (br $topmost + ;; CHECK-NEXT: (f64.const 1.2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (f64.gt + ;; CHECK-NEXT: (local.get $Int) + ;; CHECK-NEXT: (f64.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (br $topmost + ;; CHECK-NEXT: (f64.const -3.4) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (local.get $Double) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (br $topmost + ;; CHECK-NEXT: (f64.const 5.6) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (f64.lt + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (local.get $y) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (br $topmost + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $y) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $doubleCompares (type $FUNCSIG$ddd) (param $x f64) (param $y f64) (result f64) (local $t f64) @@ -273,9 +309,10 @@ ;; CHECK: (func $intOps (type $5) (result i32) ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: local.get $x - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: i32.eq + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $intOps (type $5) (result i32) (local $x i32) @@ -286,12 +323,15 @@ ) ;; CHECK: (func $hexLiterals (type $FUNCSIG$v) - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: i32.const 313249263 - ;; CHECK-NEXT: i32.add - ;; CHECK-NEXT: i32.const -19088752 - ;; CHECK-NEXT: i32.add - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 313249263) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const -19088752) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $hexLiterals (type $FUNCSIG$v) (drop @@ -307,17 +347,26 @@ ;; CHECK: (func $conversions (type $FUNCSIG$v) ;; CHECK-NEXT: (local $i i32) ;; CHECK-NEXT: (local $d f64) - ;; CHECK-NEXT: local.get $d - ;; CHECK-NEXT: call $f64-to-int - ;; CHECK-NEXT: local.set $i - ;; CHECK-NEXT: local.get $i - ;; CHECK-NEXT: f64.convert_i32_s - ;; CHECK-NEXT: local.set $d - ;; CHECK-NEXT: local.get $i - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: i32.shr_u - ;; CHECK-NEXT: f64.convert_i32_u - ;; CHECK-NEXT: local.set $d + ;; CHECK-NEXT: (block $block0 + ;; CHECK-NEXT: (local.set $i + ;; CHECK-NEXT: (call $f64-to-int + ;; CHECK-NEXT: (local.get $d) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $d + ;; CHECK-NEXT: (f64.convert_i32_s + ;; CHECK-NEXT: (local.get $i) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $d + ;; CHECK-NEXT: (f64.convert_i32_u + ;; CHECK-NEXT: (i32.shr_u + ;; CHECK-NEXT: (local.get $i) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $conversions (type $FUNCSIG$v) (local $i i32) @@ -346,14 +395,22 @@ ;; CHECK: (func $seq (type $FUNCSIG$v) ;; CHECK-NEXT: (local $J f64) - ;; CHECK-NEXT: f64.const 0.1 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: f64.const 5.1 - ;; CHECK-NEXT: f64.const 3.2 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: f64.const 4.2 - ;; CHECK-NEXT: f64.sub - ;; CHECK-NEXT: local.set $J + ;; CHECK-NEXT: (local.set $J + ;; CHECK-NEXT: (f64.sub + ;; CHECK-NEXT: (block $block0 (result f64) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (f64.const 0.1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (f64.const 5.1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $block1 (result f64) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (f64.const 3.2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (f64.const 4.2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $seq (type $FUNCSIG$v) (local $J f64) @@ -376,65 +433,90 @@ ) ;; CHECK: (func $switcher (type $6) (param $x i32) (result i32) - ;; CHECK-NEXT: block $topmost (result i32) - ;; CHECK-NEXT: block $switch-default$3 - ;; CHECK-NEXT: block $switch-case$2 - ;; CHECK-NEXT: block $switch-case$1 - ;; CHECK-NEXT: local.get $x - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: i32.sub - ;; CHECK-NEXT: br_table $switch-case$1 $switch-case$2 $switch-default$3 - ;; CHECK-NEXT: end - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: br $topmost - ;; CHECK-NEXT: end - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: br $topmost - ;; CHECK-NEXT: end - ;; CHECK-NEXT: block $switch-default$7 - ;; CHECK-NEXT: block $switch-case$6 - ;; CHECK-NEXT: block $switch-case$5 - ;; CHECK-NEXT: local.get $x - ;; CHECK-NEXT: i32.const 5 - ;; CHECK-NEXT: i32.sub - ;; CHECK-NEXT: br_table $switch-case$6 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-case$5 $switch-default$7 - ;; CHECK-NEXT: end - ;; CHECK-NEXT: i32.const 121 - ;; CHECK-NEXT: br $topmost - ;; CHECK-NEXT: end - ;; CHECK-NEXT: i32.const 51 - ;; CHECK-NEXT: br $topmost - ;; CHECK-NEXT: end - ;; CHECK-NEXT: block $label$break$Lout - ;; CHECK-NEXT: block $switch-default$16 - ;; CHECK-NEXT: block $switch-case$15 - ;; CHECK-NEXT: block $switch-case$12 - ;; CHECK-NEXT: block $switch-case$9 - ;; CHECK-NEXT: block $switch-case$8 - ;; CHECK-NEXT: local.get $x - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: i32.sub - ;; CHECK-NEXT: br_table $switch-case$15 $switch-default$16 $switch-default$16 $switch-case$12 $switch-default$16 $switch-default$16 $switch-default$16 $switch-default$16 $switch-case$9 $switch-default$16 $switch-case$8 $switch-default$16 - ;; CHECK-NEXT: end - ;; CHECK-NEXT: br $label$break$Lout - ;; CHECK-NEXT: end - ;; CHECK-NEXT: br $label$break$Lout - ;; CHECK-NEXT: end - ;; CHECK-NEXT: block $while-out$10 - ;; CHECK-NEXT: loop $while-in$11 - ;; CHECK-NEXT: br $while-out$10 - ;; CHECK-NEXT: end - ;; CHECK-NEXT: unreachable - ;; CHECK-NEXT: end - ;; CHECK-NEXT: end - ;; CHECK-NEXT: loop $while-in$14 - ;; CHECK-NEXT: br $label$break$Lout - ;; CHECK-NEXT: end - ;; CHECK-NEXT: unreachable - ;; CHECK-NEXT: end - ;; CHECK-NEXT: end - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: end + ;; CHECK-NEXT: (block $topmost (result i32) + ;; CHECK-NEXT: (block $switch$0 + ;; CHECK-NEXT: (block $switch-default$3 + ;; CHECK-NEXT: (block $switch-case$2 + ;; CHECK-NEXT: (block $switch-case$1 + ;; CHECK-NEXT: (br_table $switch-case$1 $switch-case$2 $switch-default$3 + ;; CHECK-NEXT: (i32.sub + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $topmost + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $topmost + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $switch$4 + ;; CHECK-NEXT: (block $switch-default$7 + ;; CHECK-NEXT: (block $switch-case$6 + ;; CHECK-NEXT: (block $switch-case$5 + ;; CHECK-NEXT: (br_table $switch-case$6 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-case$5 $switch-default$7 + ;; CHECK-NEXT: (i32.sub + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 5) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $topmost + ;; CHECK-NEXT: (i32.const 121) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $topmost + ;; CHECK-NEXT: (i32.const 51) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $label$break$Lout + ;; CHECK-NEXT: (block $switch-default$16 + ;; CHECK-NEXT: (block $switch-case$15 + ;; CHECK-NEXT: (block $switch-case$12 + ;; CHECK-NEXT: (block $switch-case$9 + ;; CHECK-NEXT: (block $switch-case$8 + ;; CHECK-NEXT: (br_table $switch-case$15 $switch-default$16 $switch-default$16 $switch-case$12 $switch-default$16 $switch-default$16 $switch-default$16 $switch-default$16 $switch-case$9 $switch-default$16 $switch-case$8 $switch-default$16 + ;; CHECK-NEXT: (i32.sub + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $label$break$Lout) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $label$break$Lout) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $while-out$10 + ;; CHECK-NEXT: (loop $while-in$11 + ;; CHECK-NEXT: (block $block1 + ;; CHECK-NEXT: (br $while-out$10) + ;; CHECK-NEXT: (br $while-in$11) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $label$break$Lout) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $while-out$13 + ;; CHECK-NEXT: (loop $while-in$14 + ;; CHECK-NEXT: (block $block3 + ;; CHECK-NEXT: (br $label$break$Lout) + ;; CHECK-NEXT: (br $while-in$14) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $label$break$Lout) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $switcher (type $6) (param $x i32) (result i32) (block $topmost (result i32) @@ -524,9 +606,9 @@ ) ;; CHECK: (func $blocker (type $FUNCSIG$v) - ;; CHECK-NEXT: block $label$break$L - ;; CHECK-NEXT: br $label$break$L - ;; CHECK-NEXT: end + ;; CHECK-NEXT: (block $label$break$L + ;; CHECK-NEXT: (br $label$break$L) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $blocker (type $FUNCSIG$v) (block $label$break$L @@ -535,9 +617,10 @@ ) ;; CHECK: (func $frem (type $4) (result f64) - ;; CHECK-NEXT: f64.const 5.5 - ;; CHECK-NEXT: f64.const 1.2 - ;; CHECK-NEXT: call $f64-rem + ;; CHECK-NEXT: (call $f64-rem + ;; CHECK-NEXT: (f64.const 5.5) + ;; CHECK-NEXT: (f64.const 1.2) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $frem (type $4) (result f64) (call $f64-rem @@ -548,11 +631,18 @@ ;; CHECK: (func $big_uint_div_u (type $5) (result i32) ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: i32.const -1 - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: i32.div_u - ;; CHECK-NEXT: i32.const -1 - ;; CHECK-NEXT: i32.and + ;; CHECK-NEXT: (block $topmost (result i32) + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (i32.div_u + ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const -1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $big_uint_div_u (type $5) (result i32) (local $x i32) @@ -573,19 +663,28 @@ ;; CHECK: (func $fr (type $FUNCSIG$vf) (param $x f32) ;; CHECK-NEXT: (local $y f32) ;; CHECK-NEXT: (local $z f64) - ;; CHECK-NEXT: local.get $z - ;; CHECK-NEXT: f32.demote_f64 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $y - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: f32.const 5 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: f32.const 0 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: f32.const 5 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: f32.const 0 - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (block $block0 + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (f32.demote_f64 + ;; CHECK-NEXT: (local.get $z) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $y) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (f32.const 5) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (f32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (f32.const 5) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (f32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $fr (type $FUNCSIG$vf) (param $x f32) (local $y f32) @@ -615,7 +714,7 @@ ) ;; CHECK: (func $negZero (type $4) (result f64) - ;; CHECK-NEXT: f64.const -0 + ;; CHECK-NEXT: (f64.const -0) ;; CHECK-NEXT: ) (func $negZero (type $4) (result f64) (f64.const -0) @@ -626,23 +725,36 @@ ;; CHECK-NEXT: (local $y f64) ;; CHECK-NEXT: (local $z f32) ;; CHECK-NEXT: (local $asm2wasm_i32_temp i32) - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: local.set $asm2wasm_i32_temp - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: local.get $asm2wasm_i32_temp - ;; CHECK-NEXT: i32.sub - ;; CHECK-NEXT: local.get $asm2wasm_i32_temp - ;; CHECK-NEXT: local.get $asm2wasm_i32_temp - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: i32.lt_s - ;; CHECK-NEXT: select - ;; CHECK-NEXT: local.set $x - ;; CHECK-NEXT: f64.const 0 - ;; CHECK-NEXT: f64.abs - ;; CHECK-NEXT: local.set $y - ;; CHECK-NEXT: f32.const 0 - ;; CHECK-NEXT: f32.abs - ;; CHECK-NEXT: local.set $z + ;; CHECK-NEXT: (block $block0 + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (block $block1 (result i32) + ;; CHECK-NEXT: (local.set $asm2wasm_i32_temp + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (select + ;; CHECK-NEXT: (i32.sub + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $asm2wasm_i32_temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $asm2wasm_i32_temp) + ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (local.get $asm2wasm_i32_temp) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $y + ;; CHECK-NEXT: (f64.abs + ;; CHECK-NEXT: (f64.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $z + ;; CHECK-NEXT: (f32.abs + ;; CHECK-NEXT: (f32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $abs (type $FUNCSIG$v) (local $x i32) @@ -683,14 +795,23 @@ ;; CHECK: (func $neg (type $FUNCSIG$v) ;; CHECK-NEXT: (local $x f32) - ;; CHECK-NEXT: local.get $x - ;; CHECK-NEXT: f32.neg - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: i32.const 7 - ;; CHECK-NEXT: i32.and - ;; CHECK-NEXT: i32.const 8 - ;; CHECK-NEXT: i32.add - ;; CHECK-NEXT: call_indirect $table (type $FUNCSIG$vf) + ;; CHECK-NEXT: (block $block0 + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (f32.neg + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call_indirect $table (type $FUNCSIG$vf) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.const 7) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 8) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $neg (type $FUNCSIG$v) (local $x f32) @@ -714,13 +835,16 @@ ) ;; CHECK: (func $cneg (type $FUNCSIG$vf) (param $x f32) - ;; CHECK-NEXT: local.get $x - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: i32.const 7 - ;; CHECK-NEXT: i32.and - ;; CHECK-NEXT: i32.const 8 - ;; CHECK-NEXT: i32.add - ;; CHECK-NEXT: call_indirect $table (type $FUNCSIG$vf) + ;; CHECK-NEXT: (call_indirect $table (type $FUNCSIG$vf) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (i32.const 7) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 8) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $cneg (type $FUNCSIG$vf) (param $x f32) (call_indirect (type $FUNCSIG$vf) @@ -737,12 +861,15 @@ ;; CHECK: (func $___syscall_ret (type $FUNCSIG$v) ;; CHECK-NEXT: (local $$0 i32) - ;; CHECK-NEXT: local.get $$0 - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: i32.shr_u - ;; CHECK-NEXT: i32.const -4096 - ;; CHECK-NEXT: i32.gt_u - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.gt_u + ;; CHECK-NEXT: (i32.shr_u + ;; CHECK-NEXT: (local.get $$0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const -4096) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $___syscall_ret (type $FUNCSIG$v) (local $$0 i32) @@ -758,24 +885,27 @@ ) ;; CHECK: (func $z (type $FUNCSIG$v) + ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $z (type $FUNCSIG$v) (nop) ) ;; CHECK: (func $w (type $FUNCSIG$v) + ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $w (type $FUNCSIG$v) (nop) ) ;; CHECK: (func $block_and_after (type $5) (result i32) - ;; CHECK-NEXT: block $waka - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: br $waka - ;; CHECK-NEXT: end - ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: (block $waka + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $waka) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) (func $block_and_after (type $5) (result i32) (block $waka @@ -788,11 +918,12 @@ ) ;; CHECK: (func $loop-roundtrip (type $7) (param $0 f64) (result f64) - ;; CHECK-NEXT: loop $loop-in1 (result f64) - ;; CHECK-NEXT: local.get $0 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $0 - ;; CHECK-NEXT: end + ;; CHECK-NEXT: (loop $loop-in1 (result f64) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $loop-roundtrip (type $7) (param $0 f64) (result f64) (loop $loop-in1 (result f64) @@ -804,16 +935,17 @@ ) ;; CHECK: (func $big-i64 (type $8) (result i64) - ;; CHECK-NEXT: i64.const -9218868437227405313 + ;; CHECK-NEXT: (i64.const -9218868437227405313) ;; CHECK-NEXT: ) (func $big-i64 (type $8) (result i64) (i64.const -9218868437227405313) ) ;; CHECK: (func $i64-store32 (type $9) (param $0 i32) (param $1 i64) - ;; CHECK-NEXT: local.get $0 - ;; CHECK-NEXT: local.get $1 - ;; CHECK-NEXT: i64.store32 + ;; CHECK-NEXT: (i64.store32 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $i64-store32 (type $9) (param $0 i32) (param $1 i64) (i64.store32 @@ -823,18 +955,25 @@ ) ;; CHECK: (func $return-unreachable (type $5) (result i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: return + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $return-unreachable (result i32) (return (i32.const 1)) ) ;; CHECK: (func $unreachable-block (type $5) (result i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: return + ;; CHECK-NEXT: (f64.abs + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-block (result i32) (f64.abs @@ -846,10 +985,12 @@ ) ;; CHECK: (func $unreachable-block-toplevel (type $5) (result i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: return + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-block-toplevel (result i32) (block ;; note no type - valid in binaryen IR, in wasm must be i32 @@ -859,8 +1000,13 @@ ) ;; CHECK: (func $unreachable-block0 (type $5) (result i32) - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: return + ;; CHECK-NEXT: (f64.abs + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-block0 (result i32) (f64.abs @@ -871,8 +1017,9 @@ ) ;; CHECK: (func $unreachable-block0-toplevel (type $5) (result i32) - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: return + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-block0-toplevel (result i32) (block ;; note no type - valid in binaryen IR, in wasm must be i32 @@ -881,12 +1028,13 @@ ) ;; CHECK: (func $unreachable-block-with-br (type $5) (result i32) - ;; CHECK-NEXT: block $block - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: br $block - ;; CHECK-NEXT: end - ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: (block $block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $block) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) (func $unreachable-block-with-br (result i32) (block $block ;; unreachable type due to last element having that type, but the block is exitable @@ -897,15 +1045,21 @@ ) ;; CHECK: (func $unreachable-if (type $5) (result i32) - ;; CHECK-NEXT: i32.const 3 - ;; CHECK-NEXT: if - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: return - ;; CHECK-NEXT: else - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: return - ;; CHECK-NEXT: end - ;; CHECK-NEXT: unreachable + ;; CHECK-NEXT: (f64.abs + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-if (result i32) (f64.abs @@ -922,15 +1076,19 @@ ) ;; CHECK: (func $unreachable-if-toplevel (type $5) (result i32) - ;; CHECK-NEXT: i32.const 3 - ;; CHECK-NEXT: if - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: return - ;; CHECK-NEXT: else - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: return - ;; CHECK-NEXT: end - ;; CHECK-NEXT: unreachable + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-if-toplevel (result i32) (if ;; note no type - valid in binaryen IR, in wasm must be i32 @@ -945,11 +1103,14 @@ ) ;; CHECK: (func $unreachable-loop (type $5) (result i32) - ;; CHECK-NEXT: loop - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: return - ;; CHECK-NEXT: end - ;; CHECK-NEXT: unreachable + ;; CHECK-NEXT: (f64.abs + ;; CHECK-NEXT: (loop + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-loop (result i32) (f64.abs @@ -961,11 +1122,13 @@ ) ;; CHECK: (func $unreachable-loop0 (type $5) (result i32) - ;; CHECK-NEXT: loop - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: return - ;; CHECK-NEXT: end - ;; CHECK-NEXT: unreachable + ;; CHECK-NEXT: (f64.abs + ;; CHECK-NEXT: (loop + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-loop0 (result i32) (f64.abs @@ -976,11 +1139,12 @@ ) ;; CHECK: (func $unreachable-loop-toplevel (type $5) (result i32) - ;; CHECK-NEXT: loop - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: return - ;; CHECK-NEXT: end - ;; CHECK-NEXT: unreachable + ;; CHECK-NEXT: (loop + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-loop-toplevel (result i32) (loop ;; note no type - valid in binaryen IR, in wasm must be i32 @@ -990,11 +1154,11 @@ ) ;; CHECK: (func $unreachable-loop0-toplevel (type $5) (result i32) - ;; CHECK-NEXT: loop - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: return - ;; CHECK-NEXT: end - ;; CHECK-NEXT: unreachable + ;; CHECK-NEXT: (loop + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-loop0-toplevel (result i32) (loop ;; note no type - valid in binaryen IR, in wasm must be i32 @@ -1003,7 +1167,81 @@ ) ;; CHECK: (func $unreachable-ifs (type $FUNCSIG$v) - ;; CHECK-NEXT: unreachable + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-ifs (if (unreachable) (then (nop))) @@ -1019,11 +1257,18 @@ ) ;; CHECK: (func $unreachable-if-arm (type $FUNCSIG$v) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: if - ;; CHECK-NEXT: else - ;; CHECK-NEXT: unreachable - ;; CHECK-NEXT: end + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $unreachable-if-arm (if @@ -1046,11 +1291,17 @@ ;; CHECK: (func $local-to-stack (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: call $local-to-stack - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $local-to-stack + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) (func $local-to-stack (param $x i32) (result i32) (local $temp i32) @@ -1061,12 +1312,19 @@ ;; CHECK: (func $local-to-stack-1 (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: call $local-to-stack - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: i32.eqz + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $local-to-stack + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $local-to-stack-1 (param $x i32) (result i32) (local $temp i32) @@ -1079,13 +1337,20 @@ ;; CHECK: (func $local-to-stack-1b (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: call $local-to-stack - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: i32.const 3 - ;; CHECK-NEXT: i32.add + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $local-to-stack + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $local-to-stack-1b (param $x i32) (result i32) (local $temp i32) @@ -1099,15 +1364,20 @@ ;; CHECK: (func $local-to-stack-1c-no (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: call $local-to-stack - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: i32.const 3 - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: i32.add + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $local-to-stack + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $local-to-stack-1c-no (param $x i32) (result i32) (local $temp i32) @@ -1121,15 +1391,20 @@ ;; CHECK: (func $local-to-stack-2-no (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: call $local-to-stack - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: i32.add + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $local-to-stack + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $local-to-stack-2-no (param $x i32) (result i32) (local $temp i32) @@ -1143,20 +1418,29 @@ ;; CHECK: (func $local-to-stack-3-no (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: if - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: else - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: call $local-to-stack - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: end - ;; CHECK-NEXT: i32.const 3 - ;; CHECK-NEXT: call $local-to-stack - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $local-to-stack + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $local-to-stack + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) (func $local-to-stack-3-no (param $x i32) (result i32) (local $temp i32) @@ -1175,17 +1459,30 @@ ;; CHECK: (func $local-to-stack-multi-4 (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp1 i32) ;; CHECK-NEXT: (local $temp2 i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: i32.const 3 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: i32.const 4 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (local.set $temp1 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $temp1 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 4) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $temp1) ;; CHECK-NEXT: ) (func $local-to-stack-multi-4 (param $x i32) (result i32) (local $temp1 i32) @@ -1201,17 +1498,30 @@ ;; CHECK: (func $local-to-stack-multi-5 (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp1 i32) ;; CHECK-NEXT: (local $temp2 i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: i32.const 3 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: i32.const 4 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (local.set $temp1 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $temp2 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 4) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $temp2) ;; CHECK-NEXT: ) (func $local-to-stack-multi-5 (param $x i32) (result i32) (local $temp1 i32) @@ -1227,21 +1537,33 @@ ;; CHECK: (func $local-to-stack-multi-6-justone (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp1 i32) ;; CHECK-NEXT: (local $temp2 i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: i32.const 3 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: local.set $temp2 - ;; CHECK-NEXT: i32.const 4 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $temp2 - ;; CHECK-NEXT: local.get $temp2 - ;; CHECK-NEXT: i32.add + ;; CHECK-NEXT: (local.set $temp1 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $temp2 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 4) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (local.get $temp2) + ;; CHECK-NEXT: (local.get $temp2) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $local-to-stack-multi-6-justone (param $x i32) (result i32) (local $temp1 i32) @@ -1260,21 +1582,33 @@ ;; CHECK: (func $local-to-stack-multi-7-justone (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp1 i32) ;; CHECK-NEXT: (local $temp2 i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: local.set $temp1 - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $temp1 - ;; CHECK-NEXT: local.get $temp1 - ;; CHECK-NEXT: i32.add - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: i32.const 3 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: i32.const 4 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (local.set $temp1 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (local.get $temp1) + ;; CHECK-NEXT: (local.get $temp1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $temp2 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 4) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $temp2) ;; CHECK-NEXT: ) (func $local-to-stack-multi-7-justone (param $x i32) (result i32) (local $temp1 i32) @@ -1295,16 +1629,25 @@ ;; CHECK: (func $local-to-stack-overlapping-multi-8-no (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp1 i32) ;; CHECK-NEXT: (local $temp2 i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: local.set $temp1 - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: i32.const 3 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $temp1 - ;; CHECK-NEXT: i32.add + ;; CHECK-NEXT: (local.set $temp1 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $temp2 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (local.get $temp2) + ;; CHECK-NEXT: (local.get $temp1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $local-to-stack-overlapping-multi-8-no (param $x i32) (result i32) (local $temp1 i32) @@ -1321,14 +1664,25 @@ ;; CHECK: (func $local-to-stack-overlapping-multi-9-yes (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp1 i32) ;; CHECK-NEXT: (local $temp2 i32) - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: i32.const 3 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: i32.add + ;; CHECK-NEXT: (local.set $temp1 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $temp2 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (local.get $temp1) + ;; CHECK-NEXT: (local.get $temp2) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $local-to-stack-overlapping-multi-9-yes (param $x i32) (result i32) (local $temp1 i32) @@ -1345,21 +1699,39 @@ ;; CHECK: (func $local-to-stack-through-control-flow (type $FUNCSIG$v) ;; CHECK-NEXT: (local $temp1 i32) ;; CHECK-NEXT: (local $temp2 i32) - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: if - ;; CHECK-NEXT: end - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: block $block - ;; CHECK-NEXT: br $block - ;; CHECK-NEXT: end - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (local.set $temp2 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $temp1 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $temp1 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $block + ;; CHECK-NEXT: (br $block) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp2) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $local-to-stack-through-control-flow (local $temp1 i32) @@ -1376,16 +1748,29 @@ ;; CHECK: (func $local-to-stack-in-control-flow (type $FUNCSIG$v) ;; CHECK-NEXT: (local $temp1 i32) - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: if - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: else - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $local-to-stack-multi-4 - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: end + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp1 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp1 + ;; CHECK-NEXT: (call $local-to-stack-multi-4 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $local-to-stack-in-control-flow (local $temp1 i32) @@ -1407,15 +1792,26 @@ ;; CHECK: (func $remove-block (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: call $remove-block - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: call $remove-block - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: call $remove-block - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: i32.eqz - ;; CHECK-NEXT: i32.add + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (call $remove-block + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (call $remove-block + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $remove-block + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $remove-block (param $x i32) (result i32) (local $temp i32) @@ -1434,13 +1830,17 @@ ;; CHECK: (func $tuple-local2stack (type $FUNCSIG$v) ;; CHECK-NEXT: (local $pair (tuple f32 i32)) ;; CHECK-NEXT: (local $f32 f32) - ;; CHECK-NEXT: f32.const 0 - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: tuple.make 2 - ;; CHECK-NEXT: local.set $pair - ;; CHECK-NEXT: local.get $pair - ;; CHECK-NEXT: tuple.extract 2 0 - ;; CHECK-NEXT: local.set $f32 + ;; CHECK-NEXT: (local.set $pair + ;; CHECK-NEXT: (tuple.make 2 + ;; CHECK-NEXT: (f32.const 0) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $f32 + ;; CHECK-NEXT: (tuple.extract 2 0 + ;; CHECK-NEXT: (local.get $pair) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $tuple-local2stack (local $pair (tuple f32 i32)) diff --git a/test/lit/passes/stack-ir-eh.wast b/test/lit/passes/stack-ir-eh.wast index e06e5e5172d..86895ddd431 100644 --- a/test/lit/passes/stack-ir-eh.wast +++ b/test/lit/passes/stack-ir-eh.wast @@ -11,25 +11,28 @@ (func $foo) ;; CHECK: (func $test (type $0) - ;; CHECK-NEXT: block $outer - ;; CHECK-NEXT: block $l-catch (result i32) - ;; CHECK-NEXT: block $l-catch-ref (type $1) (result i32 exnref) - ;; CHECK-NEXT: block $l-catch-all - ;; CHECK-NEXT: block $l-catch-all-ref (result exnref) - ;; CHECK-NEXT: try_table (catch $e-i32 $l-catch) (catch_ref $e-i32 $l-catch-ref) (catch_all $l-catch-all) (catch_all_ref $l-catch-all-ref) - ;; CHECK-NEXT: call $foo - ;; CHECK-NEXT: end - ;; CHECK-NEXT: br $outer - ;; CHECK-NEXT: end - ;; CHECK-NEXT: throw_ref - ;; CHECK-NEXT: end - ;; CHECK-NEXT: br $outer - ;; CHECK-NEXT: end - ;; CHECK-NEXT: tuple.drop 2 - ;; CHECK-NEXT: br $outer - ;; CHECK-NEXT: end - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: end + ;; CHECK-NEXT: (block $outer + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block $l-catch (result i32) + ;; CHECK-NEXT: (tuple.drop 2 + ;; CHECK-NEXT: (block $l-catch-ref (type $1) (result i32 exnref) + ;; CHECK-NEXT: (block $l-catch-all + ;; CHECK-NEXT: (throw_ref + ;; CHECK-NEXT: (block $l-catch-all-ref (result exnref) + ;; CHECK-NEXT: (try_table (catch $e-i32 $l-catch) (catch_ref $e-i32 $l-catch-ref) (catch_all $l-catch-all) (catch_all_ref $l-catch-all-ref) + ;; CHECK-NEXT: (call $foo) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $outer) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $outer) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $outer) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $test (block $outer diff --git a/test/lit/passes/stack-ir-non-nullable.wast b/test/lit/passes/stack-ir-non-nullable.wast index c3309d65a74..c705375be95 100644 --- a/test/lit/passes/stack-ir-non-nullable.wast +++ b/test/lit/passes/stack-ir-non-nullable.wast @@ -61,20 +61,32 @@ ;; CHECK: (func $if-no-last-get (type $1) (param $param (ref eq)) (result (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: ref.eq - ;; CHECK-NEXT: if - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: else - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $param) ;; CHECK-NEXT: ) (func $if-no-last-get (param $param (ref eq)) (result (ref eq)) ;; As the original, but now there is no final get, so we can remove the set- @@ -110,20 +122,35 @@ ;; CHECK: (func $if-extra-set (type $1) (param $param (ref eq)) (result (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: ref.eq - ;; CHECK-NEXT: if - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: else - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) (func $if-extra-set (param $param (ref eq)) (result (ref eq)) ;; As the original, but now there is an extra set before the final get, so @@ -162,24 +189,35 @@ ;; CHECK: (func $if-wrong-extra-set (type $1) (param $param (ref eq)) (result (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: ref.eq - ;; CHECK-NEXT: if - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: else - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $param - ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $param + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) (func $if-wrong-extra-set (param $param (ref eq)) (result (ref eq)) ;; As the last testcase, but the extra set's index is wrong, so we cannot @@ -218,22 +256,35 @@ ;; CHECK: (func $if-wrong-extra-get (type $1) (param $param (ref eq)) (result (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: ref.eq - ;; CHECK-NEXT: if - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: else - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $param) ;; CHECK-NEXT: ) (func $if-wrong-extra-get (param $param (ref eq)) (result (ref eq)) ;; As the last testcase, but now it is the get that has the wrong index to @@ -272,20 +323,32 @@ ) ;; CHECK: (func $if-param (type $2) (param $param (ref eq)) (param $temp (ref eq)) (result (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: ref.eq - ;; CHECK-NEXT: if - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: else - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) (func $if-param (param $param (ref eq)) (param $temp (ref eq)) (result (ref eq)) ;; As the original testcase, but now $temp is a param. Validation is no @@ -320,20 +383,32 @@ ;; CHECK: (func $if-nullable (type $3) (param $param (ref eq)) (result eqref) ;; CHECK-NEXT: (local $temp eqref) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: ref.eq - ;; CHECK-NEXT: if - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: else - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) (func $if-nullable (param $param (ref eq)) (result (ref null eq)) (local $temp (ref null eq)) ;; this changed @@ -369,30 +444,45 @@ ;; CHECK: (func $if-nondefaultable (type $1) (param $param (ref eq)) (result (ref eq)) ;; CHECK-NEXT: (local $temp (tuple i32 (ref eq))) - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: tuple.make 2 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: tuple.extract 2 1 - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: ref.eq - ;; CHECK-NEXT: if - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: i32.const 3 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: tuple.make 2 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: else - ;; CHECK-NEXT: i32.const 4 - ;; CHECK-NEXT: i32.const 5 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: tuple.make 2 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: tuple.extract 2 1 + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (tuple.make 2 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (tuple.extract 2 1 + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (tuple.make 2 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (tuple.make 2 + ;; CHECK-NEXT: (i32.const 4) + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 5) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (tuple.extract 2 1 + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $if-nondefaultable (param $param (ref eq)) (result (ref eq)) (local $temp (tuple i32 (ref eq))) @@ -442,30 +532,45 @@ ;; CHECK: (func $if-defaultable (type $4) (param $param eqref) (result eqref) ;; CHECK-NEXT: (local $temp (tuple i32 eqref)) - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: tuple.make 2 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: tuple.extract 2 1 - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: ref.eq - ;; CHECK-NEXT: if - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: i32.const 3 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: tuple.make 2 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: else - ;; CHECK-NEXT: i32.const 4 - ;; CHECK-NEXT: i32.const 5 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: tuple.make 2 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: tuple.extract 2 1 + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (tuple.make 2 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (tuple.extract 2 1 + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (tuple.make 2 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (tuple.make 2 + ;; CHECK-NEXT: (i32.const 4) + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 5) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (tuple.extract 2 1 + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $if-defaultable (param $param (ref null eq)) (result (ref null eq)) (local $temp (tuple i32 (ref null eq))) @@ -514,16 +619,25 @@ ;; CHECK: (func $if-non-ref (type $5) (param $param i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: i32.eqz - ;; CHECK-NEXT: if - ;; CHECK-NEXT: i32.const 1 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: else - ;; CHECK-NEXT: i32.const 2 - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) (func $if-non-ref (param $param i32) (result i32) (local $temp i32) @@ -552,26 +666,37 @@ ;; CHECK: (func $nesting (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: if - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: else - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $nesting (param $param (ref eq)) (local $temp (ref eq)) @@ -617,20 +742,31 @@ ;; CHECK: (func $nesting-left (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: if - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: else - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: end + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $nesting-left (param $param (ref eq)) (local $temp (ref eq)) @@ -669,20 +805,31 @@ ;; CHECK: (func $nesting-right (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: if - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: else - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: end + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $nesting-right (param $param (ref eq)) (local $temp (ref eq)) @@ -721,16 +868,28 @@ ;; CHECK: (func $nesting-both (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: if - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: else - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: end + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $nesting-both (param $param (ref eq)) (local $temp (ref eq)) @@ -767,14 +926,25 @@ ;; CHECK: (func $nesting-both-less (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: if - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: else - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: end + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $nesting-both-less (param $param (ref eq)) (local $temp (ref eq)) @@ -807,16 +977,31 @@ ;; CHECK: (func $nesting-both-after (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: if - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: else - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $nesting-both-after (param $param (ref eq)) (local $temp (ref eq)) @@ -856,8 +1041,14 @@ ;; CHECK: (func $nesting-irrelevant (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $block + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $nesting-irrelevant (param $param (ref eq)) (local $temp (ref eq)) @@ -875,12 +1066,17 @@ ;; CHECK: (func $nesting-relevant (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $nesting-relevant (param $param (ref eq)) (local $temp (ref eq)) @@ -900,10 +1096,20 @@ ;; CHECK: (func $nesting-after (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $block + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $nesting-after (param $param (ref eq)) (local $temp (ref eq)) @@ -926,10 +1132,20 @@ ;; CHECK: (func $nesting-reverse (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (block $block + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $nesting-reverse (param $param (ref eq)) (local $temp (ref eq)) @@ -953,16 +1169,23 @@ ;; CHECK: (func $nesting-covered-but-ended (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: drop - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: drop + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $block + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $nesting-covered-but-ended (param $param (ref eq)) (local $temp (ref eq)) @@ -991,21 +1214,30 @@ ;; CHECK: (func $two-covers (type $1) (param $param (ref eq)) (result (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: local.get $temp - ;; CHECK-NEXT: i32.const 0 - ;; CHECK-NEXT: ref.i31 - ;; CHECK-NEXT: ref.eq - ;; CHECK-NEXT: if - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.tee $temp - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: else - ;; CHECK-NEXT: local.get $param - ;; CHECK-NEXT: local.set $temp - ;; CHECK-NEXT: end - ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.eq + ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: (ref.i31 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (then + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.tee $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (else + ;; CHECK-NEXT: (local.set $temp + ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $temp) ;; CHECK-NEXT: ) (func $two-covers (param $param (ref eq)) (result (ref eq)) (local $temp (ref eq)) diff --git a/test/lit/passes/translate-to-new-eh.wast b/test/lit/passes/translate-to-new-eh.wast index 10de158d4b6..0e9770f72de 100644 --- a/test/lit/passes/translate-to-new-eh.wast +++ b/test/lit/passes/translate-to-new-eh.wast @@ -52,12 +52,14 @@ ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $bar (type $1) + ;; STACKIR-OPT-NEXT: (nop) ;; STACKIR-OPT-NEXT: ) (func $bar) ;; CHECK: (func $baz (type $1) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $baz (type $1) + ;; STACKIR-OPT-NEXT: (nop) ;; STACKIR-OPT-NEXT: ) (func $baz) @@ -82,19 +84,19 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-none-tag-none (type $1) - ;; STACKIR-OPT-NEXT: block $outer0 - ;; STACKIR-OPT-NEXT: block $catch_all2 - ;; STACKIR-OPT-NEXT: block $catch1 - ;; STACKIR-OPT-NEXT: try_table (catch $e-empty $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: call $bar - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 + ;; STACKIR-OPT-NEXT: (block $catch_all2 + ;; STACKIR-OPT-NEXT: (block $catch1 + ;; STACKIR-OPT-NEXT: (try_table (catch $e-empty $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (br $outer0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (call $bar) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-none-tag-none ;; try's type is none and catch's tag type is none @@ -136,18 +138,26 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-none-tag-none-with-rethrow (type $1) ;; STACKIR-OPT-NEXT: (local $0 exnref) - ;; STACKIR-OPT-NEXT: block $outer0 - ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: block $catch1 (result exnref) - ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch1 (result exnref) + ;; STACKIR-OPT-NEXT: (try_table (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-none-tag-none-with-rethrow ;; try's type is none and catch's tag type is none, and there are rethrows @@ -186,19 +196,23 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-none-tag-single (type $1) ;; STACKIR-OPT-NEXT: (local $0 i32) - ;; STACKIR-OPT-NEXT: block $outer0 - ;; STACKIR-OPT-NEXT: block $catch_all2 - ;; STACKIR-OPT-NEXT: block $catch1 (result i32) - ;; STACKIR-OPT-NEXT: try_table (catch $e-i32 $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: drop - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: call $bar - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 + ;; STACKIR-OPT-NEXT: (block $catch_all2 + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch1 (result i32) + ;; STACKIR-OPT-NEXT: (try_table (catch $e-i32 $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (drop + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (call $bar) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-none-tag-single ;; try's type is none and catch's tag type is single @@ -261,26 +275,41 @@ ;; STACKIR-OPT-NEXT: (local $0 exnref) ;; STACKIR-OPT-NEXT: (local $1 i32) ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 exnref)) - ;; STACKIR-OPT-NEXT: block $outer0 - ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: block $catch1 (type $3) (result i32 exnref) - ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: local.set $2 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 2 0 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 2 1 - ;; STACKIR-OPT-NEXT: local.set $0 - ;; STACKIR-OPT-NEXT: drop - ;; STACKIR-OPT-NEXT: local.get $0 - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: (local.set $2 + ;; STACKIR-OPT-NEXT: (block $catch1 (type $3) (result i32 exnref) + ;; STACKIR-OPT-NEXT: (try_table (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $1 + ;; STACKIR-OPT-NEXT: (tuple.extract 2 0 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (tuple.extract 2 1 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (block + ;; STACKIR-OPT-NEXT: (drop + ;; STACKIR-OPT-NEXT: (local.get $1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-none-tag-single-with-rethrow ;; try's type is none and catch's tag type is single, and there are rethrows @@ -322,21 +351,23 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-none-tag-tuple (type $1) ;; STACKIR-OPT-NEXT: (local $0 (tuple i32 i64)) - ;; STACKIR-OPT-NEXT: block $outer0 - ;; STACKIR-OPT-NEXT: block $catch_all2 - ;; STACKIR-OPT-NEXT: block $catch1 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: try_table (catch $e-i32-i64 $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: local.set $0 - ;; STACKIR-OPT-NEXT: local.get $0 - ;; STACKIR-OPT-NEXT: tuple.drop 2 - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: call $bar - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 + ;; STACKIR-OPT-NEXT: (block $catch_all2 + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch1 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: (try_table (catch $e-i32-i64 $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (tuple.drop 2 + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (call $bar) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-none-tag-tuple ;; try's type is none and catch's tag type is tuple @@ -404,29 +435,46 @@ ;; STACKIR-OPT-NEXT: (local $0 exnref) ;; STACKIR-OPT-NEXT: (local $1 (tuple i32 i64)) ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 i64 exnref)) - ;; STACKIR-OPT-NEXT: block $outer0 - ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: block $catch1 (type $4) (result i32 i64 exnref) - ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: local.set $2 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 3 0 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 3 1 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: local.set $1 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 3 2 - ;; STACKIR-OPT-NEXT: local.get $1 - ;; STACKIR-OPT-NEXT: tuple.drop 2 - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: (local.set $2 + ;; STACKIR-OPT-NEXT: (block $catch1 (type $4) (result i32 i64 exnref) + ;; STACKIR-OPT-NEXT: (try_table (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $1 + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (tuple.extract 3 0 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (tuple.extract 3 1 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (tuple.extract 3 2 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (block + ;; STACKIR-OPT-NEXT: (tuple.drop 2 + ;; STACKIR-OPT-NEXT: (local.get $1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-none-tag-tuple-with-rethrow ;; try's type is none and catch's tag type is tuple, and there are rethrows @@ -465,20 +513,22 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-single-tag-none (type $2) (result i32) - ;; STACKIR-OPT-NEXT: block $outer0 (result i32) - ;; STACKIR-OPT-NEXT: block $catch_all2 - ;; STACKIR-OPT-NEXT: block $catch1 - ;; STACKIR-OPT-NEXT: try_table (result i32) (catch $e-empty $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: i32.const 1 - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: i32.const 2 - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 (result i32) + ;; STACKIR-OPT-NEXT: (block $catch_all2 + ;; STACKIR-OPT-NEXT: (block $catch1 + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch $e-empty $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (i32.const 1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (i32.const 2) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-single-tag-none (result i32) ;; try's type is single and catch's tag type is none @@ -523,19 +573,28 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-single-tag-none-with-rethrow (type $2) (result i32) ;; STACKIR-OPT-NEXT: (local $0 exnref) - ;; STACKIR-OPT-NEXT: block $outer0 (result i32) - ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: block $catch1 (result exnref) - ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 (result i32) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch1 (result exnref) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-single-tag-none-with-rethrow (result i32) ;; try's type is single and catch's tag type is none, and there are rethrows @@ -576,19 +635,24 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-single-tag-single (type $2) (result i32) ;; STACKIR-OPT-NEXT: (local $0 i32) - ;; STACKIR-OPT-NEXT: block $outer0 (result i32) - ;; STACKIR-OPT-NEXT: block $catch_all2 - ;; STACKIR-OPT-NEXT: block $catch1 (result i32) - ;; STACKIR-OPT-NEXT: try_table (result i32) (catch $e-i32 $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: i32.const 2 - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 (result i32) + ;; STACKIR-OPT-NEXT: (block $catch_all2 + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch1 (result i32) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch $e-i32 $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (i32.const 2) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-single-tag-single (result i32) ;; try's type is single and catch's tag type is single @@ -654,27 +718,45 @@ ;; STACKIR-OPT-NEXT: (local $0 exnref) ;; STACKIR-OPT-NEXT: (local $1 i32) ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 exnref)) - ;; STACKIR-OPT-NEXT: block $outer0 (result i32) - ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: block $catch1 (type $3) (result i32 exnref) - ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: local.set $2 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 2 0 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 2 1 - ;; STACKIR-OPT-NEXT: local.set $0 - ;; STACKIR-OPT-NEXT: drop - ;; STACKIR-OPT-NEXT: local.get $0 - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 (result i32) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: (local.set $2 + ;; STACKIR-OPT-NEXT: (block $catch1 (type $3) (result i32 exnref) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $1 + ;; STACKIR-OPT-NEXT: (tuple.extract 2 0 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (tuple.extract 2 1 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (block (result i32) + ;; STACKIR-OPT-NEXT: (drop + ;; STACKIR-OPT-NEXT: (local.get $1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-single-tag-single-with-rethrow (result i32) ;; try's type is single and catch's tag type is single, and there are @@ -724,23 +806,29 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-single-tag-tuple (type $2) (result i32) ;; STACKIR-OPT-NEXT: (local $0 (tuple i32 i64)) - ;; STACKIR-OPT-NEXT: block $outer0 (result i32) - ;; STACKIR-OPT-NEXT: block $catch_all2 - ;; STACKIR-OPT-NEXT: block $catch1 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: try_table (result i32) (catch $e-i32-i64 $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: local.set $0 - ;; STACKIR-OPT-NEXT: local.get $0 - ;; STACKIR-OPT-NEXT: tuple.drop 2 - ;; STACKIR-OPT-NEXT: i32.const 1 - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: i32.const 2 - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 (result i32) + ;; STACKIR-OPT-NEXT: (block $catch_all2 + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch1 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch $e-i32-i64 $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (block (result i32) + ;; STACKIR-OPT-NEXT: (tuple.drop 2 + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (i32.const 1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (i32.const 2) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-single-tag-tuple (result i32) ;; try's type is single and catch's tag type is tuple @@ -814,30 +902,50 @@ ;; STACKIR-OPT-NEXT: (local $0 exnref) ;; STACKIR-OPT-NEXT: (local $1 (tuple i32 i64)) ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 i64 exnref)) - ;; STACKIR-OPT-NEXT: block $outer0 (result i32) - ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: block $catch1 (type $4) (result i32 i64 exnref) - ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: local.set $2 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 3 0 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 3 1 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: local.set $1 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 3 2 - ;; STACKIR-OPT-NEXT: local.get $1 - ;; STACKIR-OPT-NEXT: tuple.drop 2 - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 (result i32) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: (local.set $2 + ;; STACKIR-OPT-NEXT: (block $catch1 (type $4) (result i32 i64 exnref) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $1 + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (tuple.extract 3 0 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (tuple.extract 3 1 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (tuple.extract 3 2 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (block (result i32) + ;; STACKIR-OPT-NEXT: (tuple.drop 2 + ;; STACKIR-OPT-NEXT: (local.get $1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-single-tag-tuple-with-rethrow (result i32) ;; try's type is single and catch's tag type is tuple, and there are @@ -887,26 +995,31 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-tuple-tag-none (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: block $catch_all2 - ;; STACKIR-OPT-NEXT: block $catch1 - ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch $e-empty $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: i64.const 0 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: i32.const 1 - ;; STACKIR-OPT-NEXT: i64.const 1 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: i32.const 2 - ;; STACKIR-OPT-NEXT: i64.const 0 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: (block $catch_all2 + ;; STACKIR-OPT-NEXT: (block $catch1 + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (try_table (type $0) (result i32 i64) (catch $e-empty $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: (i64.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (i32.const 1) + ;; STACKIR-OPT-NEXT: (i64.const 1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (i32.const 2) + ;; STACKIR-OPT-NEXT: (i64.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-tuple-tag-none (result i32 i64) ;; try's type is tuple and catch's tag type is none @@ -963,21 +1076,31 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-tuple-tag-none-with-rethrow (type $0) (result i32 i64) ;; STACKIR-OPT-NEXT: (local $0 exnref) - ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: block $catch1 (result exnref) - ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: i64.const 0 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch1 (result exnref) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (try_table (type $0) (result i32 i64) (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: (i64.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-tuple-tag-none-with-rethrow (result i32 i64) ;; try's type is tuple and catch's tag type is none, and there are rethrows @@ -1030,25 +1153,33 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-tuple-tag-single (type $0) (result i32 i64) ;; STACKIR-OPT-NEXT: (local $0 i32) - ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: block $catch_all2 - ;; STACKIR-OPT-NEXT: block $catch1 (result i32) - ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch $e-i32 $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: i64.const 0 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: i64.const 0 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: i32.const 2 - ;; STACKIR-OPT-NEXT: i64.const 2 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: (block $catch_all2 + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch1 (result i32) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (try_table (type $0) (result i32 i64) (catch $e-i32 $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: (i64.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: (i64.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (i32.const 2) + ;; STACKIR-OPT-NEXT: (i64.const 2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-tuple-tag-single (result i32 i64) ;; try's type is tuple and catch's tag type is single @@ -1126,29 +1257,48 @@ ;; STACKIR-OPT-NEXT: (local $0 exnref) ;; STACKIR-OPT-NEXT: (local $1 i32) ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 exnref)) - ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: block $catch1 (type $3) (result i32 exnref) - ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: i64.const 0 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: local.set $2 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 2 0 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 2 1 - ;; STACKIR-OPT-NEXT: local.set $0 - ;; STACKIR-OPT-NEXT: drop - ;; STACKIR-OPT-NEXT: local.get $0 - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: (local.set $2 + ;; STACKIR-OPT-NEXT: (block $catch1 (type $3) (result i32 exnref) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (try_table (type $0) (result i32 i64) (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: (i64.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $1 + ;; STACKIR-OPT-NEXT: (tuple.extract 2 0 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (tuple.extract 2 1 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (block (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: (drop + ;; STACKIR-OPT-NEXT: (local.get $1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-tuple-tag-single-with-rethrow (result i32 i64) ;; try's type is tuple and catch's tag type is single, and there are @@ -1202,25 +1352,30 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-tuple-tag-tuple (type $0) (result i32 i64) ;; STACKIR-OPT-NEXT: (local $0 (tuple i32 i64)) - ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: block $catch_all2 - ;; STACKIR-OPT-NEXT: block $catch1 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch $e-i32-i64 $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: i64.const 0 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: local.set $0 - ;; STACKIR-OPT-NEXT: local.get $0 - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: i32.const 2 - ;; STACKIR-OPT-NEXT: i64.const 2 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: (block $catch_all2 + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch1 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (try_table (type $0) (result i32 i64) (catch $e-i32-i64 $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: (i64.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (i32.const 2) + ;; STACKIR-OPT-NEXT: (i64.const 2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-tuple-tag-tuple (result i32 i64) ;; try's type is tuple and catch's tag type is tuple @@ -1300,32 +1455,53 @@ ;; STACKIR-OPT-NEXT: (local $0 exnref) ;; STACKIR-OPT-NEXT: (local $1 (tuple i32 i64)) ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 i64 exnref)) - ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: block $catch1 (type $4) (result i32 i64 exnref) - ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: i64.const 0 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: local.set $2 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 3 0 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 3 1 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: local.set $1 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.extract 3 2 - ;; STACKIR-OPT-NEXT: local.get $1 - ;; STACKIR-OPT-NEXT: tuple.drop 2 - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: (local.set $2 + ;; STACKIR-OPT-NEXT: (block $catch1 (type $4) (result i32 i64 exnref) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (try_table (type $0) (result i32 i64) (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: (i64.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $1 + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (tuple.extract 3 0 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (tuple.extract 3 1 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (tuple.extract 3 2 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0 + ;; STACKIR-OPT-NEXT: (block (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: (tuple.drop 2 + ;; STACKIR-OPT-NEXT: (local.get $1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-tuple-tag-tuple-with-rethrow (result i32 i64) ;; try's type is tuple and catch's tag type is tuple, and there are @@ -1359,9 +1535,9 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $catchless-delegateless-try (type $1) - ;; STACKIR-OPT-NEXT: try_table - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (try_table + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $catchless-delegateless-try (try @@ -1453,43 +1629,75 @@ ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 i64)) ;; STACKIR-OPT-NEXT: (local $3 (tuple i32 exnref)) ;; STACKIR-OPT-NEXT: (local $4 (tuple i32 i64 exnref)) - ;; STACKIR-OPT-NEXT: block $outer0 - ;; STACKIR-OPT-NEXT: block $catch_all4 (result exnref) - ;; STACKIR-OPT-NEXT: block $catch3 (type $4) (result i32 i64 exnref) - ;; STACKIR-OPT-NEXT: block $catch2 (type $3) (result i32 exnref) - ;; STACKIR-OPT-NEXT: block $catch1 (result exnref) - ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-empty $catch1) (catch_ref $e-i32 $catch2) (catch_ref $e-i32-i64 $catch3) (catch_all_ref $catch_all4) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: local.set $3 - ;; STACKIR-OPT-NEXT: local.get $3 - ;; STACKIR-OPT-NEXT: tuple.extract 2 0 - ;; STACKIR-OPT-NEXT: local.get $3 - ;; STACKIR-OPT-NEXT: tuple.extract 2 1 - ;; STACKIR-OPT-NEXT: local.set $0 - ;; STACKIR-OPT-NEXT: drop - ;; STACKIR-OPT-NEXT: local.get $0 - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: local.set $4 - ;; STACKIR-OPT-NEXT: local.get $4 - ;; STACKIR-OPT-NEXT: tuple.extract 3 0 - ;; STACKIR-OPT-NEXT: local.get $4 - ;; STACKIR-OPT-NEXT: tuple.extract 3 1 - ;; STACKIR-OPT-NEXT: tuple.make 2 - ;; STACKIR-OPT-NEXT: local.set $2 - ;; STACKIR-OPT-NEXT: local.get $4 - ;; STACKIR-OPT-NEXT: tuple.extract 3 2 - ;; STACKIR-OPT-NEXT: local.get $2 - ;; STACKIR-OPT-NEXT: tuple.drop 2 - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer0 + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch_all4 (result exnref) + ;; STACKIR-OPT-NEXT: (local.set $4 + ;; STACKIR-OPT-NEXT: (block $catch3 (type $4) (result i32 i64 exnref) + ;; STACKIR-OPT-NEXT: (local.set $3 + ;; STACKIR-OPT-NEXT: (block $catch2 (type $3) (result i32 exnref) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch1 (result exnref) + ;; STACKIR-OPT-NEXT: (try_table (catch_ref $e-empty $catch1) (catch_ref $e-i32 $catch2) (catch_ref $e-i32-i64 $catch3) (catch_all_ref $catch_all4) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $1 + ;; STACKIR-OPT-NEXT: (tuple.extract 2 0 + ;; STACKIR-OPT-NEXT: (local.get $3) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (tuple.extract 2 1 + ;; STACKIR-OPT-NEXT: (local.get $3) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (block + ;; STACKIR-OPT-NEXT: (drop + ;; STACKIR-OPT-NEXT: (local.get $1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $2 + ;; STACKIR-OPT-NEXT: (tuple.make 2 + ;; STACKIR-OPT-NEXT: (tuple.extract 3 0 + ;; STACKIR-OPT-NEXT: (local.get $4) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (tuple.extract 3 1 + ;; STACKIR-OPT-NEXT: (local.get $4) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (tuple.extract 3 2 + ;; STACKIR-OPT-NEXT: (local.get $4) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (block + ;; STACKIR-OPT-NEXT: (tuple.drop 2 + ;; STACKIR-OPT-NEXT: (local.get $2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $multiple-catches-and-catch_all (try $l0 @@ -1552,28 +1760,34 @@ ;; STACKIR-OPT: (func $nested-catch-rethrows (type $1) ;; STACKIR-OPT-NEXT: (local $0 exnref) ;; STACKIR-OPT-NEXT: (local $1 exnref) - ;; STACKIR-OPT-NEXT: block $outer3 - ;; STACKIR-OPT-NEXT: block $catch_all4 (result exnref) - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $catch_all4) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer3 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: local.set $0 - ;; STACKIR-OPT-NEXT: block $outer0 - ;; STACKIR-OPT-NEXT: block $catch2 (result exnref) - ;; STACKIR-OPT-NEXT: block $catch1 - ;; STACKIR-OPT-NEXT: try_table (catch $e-empty $catch1) (catch_ref $e-empty $catch2) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: local.get $0 - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer3 + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch_all4 (result exnref) + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $catch_all4) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer3) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (block $outer0 + ;; STACKIR-OPT-NEXT: (local.set $1 + ;; STACKIR-OPT-NEXT: (block $catch2 (result exnref) + ;; STACKIR-OPT-NEXT: (block $catch1 + ;; STACKIR-OPT-NEXT: (try_table (catch $e-empty $catch1) (catch_ref $e-empty $catch2) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $nested-catch-rethrows (try $l0 @@ -1625,22 +1839,23 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $delegate-target-outer-try-none (type $1) - ;; STACKIR-OPT-NEXT: block $outer1 - ;; STACKIR-OPT-NEXT: block $catch_all2 - ;; STACKIR-OPT-NEXT: try_table (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: block $l00 (result exnref) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) - ;; STACKIR-OPT-NEXT: call $bar - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: call $baz - ;; STACKIR-OPT-NEXT: br $outer1 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: unreachable - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer1 + ;; STACKIR-OPT-NEXT: (block $catch_all2 + ;; STACKIR-OPT-NEXT: (try_table (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $l00 (result exnref) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l00) + ;; STACKIR-OPT-NEXT: (call $bar) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (call $baz) + ;; STACKIR-OPT-NEXT: (br $outer1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (nop) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $delegate-target-outer-try-none ;; An inner try-delegate targets an outer try whose type is none @@ -1682,25 +1897,26 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $multiple-delegates-target-outer-try-none (type $1) - ;; STACKIR-OPT-NEXT: block $outer1 - ;; STACKIR-OPT-NEXT: block $catch_all2 - ;; STACKIR-OPT-NEXT: try_table (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: block $l00 (result exnref) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) - ;; STACKIR-OPT-NEXT: call $bar - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) - ;; STACKIR-OPT-NEXT: call $bar - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: call $baz - ;; STACKIR-OPT-NEXT: br $outer1 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: unreachable - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer1 + ;; STACKIR-OPT-NEXT: (block $catch_all2 + ;; STACKIR-OPT-NEXT: (try_table (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $l00 (result exnref) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l00) + ;; STACKIR-OPT-NEXT: (call $bar) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l00) + ;; STACKIR-OPT-NEXT: (call $bar) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (call $baz) + ;; STACKIR-OPT-NEXT: (br $outer1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (nop) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $multiple-delegates-target-outer-try-none ;; Multiple inner try-delegates target an outer try whose type is none @@ -1750,23 +1966,28 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $delegate-target-outer-try-concrete (type $2) (result i32) - ;; STACKIR-OPT-NEXT: block $outer1 (result i32) - ;; STACKIR-OPT-NEXT: block $catch_all2 - ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: block $l00 (result exnref) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_all_ref $l00) - ;; STACKIR-OPT-NEXT: call $bar - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer1 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer1 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: i32.const 1 - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer1 (result i32) + ;; STACKIR-OPT-NEXT: (block $catch_all2 + ;; STACKIR-OPT-NEXT: (br $outer1 + ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $l00 (result exnref) + ;; STACKIR-OPT-NEXT: (br $outer1 + ;; STACKIR-OPT-NEXT: (block (result i32) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch_all_ref $l00) + ;; STACKIR-OPT-NEXT: (call $bar) + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (i32.const 1) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $delegate-target-outer-try-concrete (result i32) ;; An inner try-delegate targets an outer try whose type is concrete @@ -1800,16 +2021,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $deletate-target-outer-try-unreachable (type $1) - ;; STACKIR-OPT-NEXT: try_table - ;; STACKIR-OPT-NEXT: block $l00 (result exnref) - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: return - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: unreachable + ;; STACKIR-OPT-NEXT: (try_table + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $l00 (result exnref) + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l00) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (return) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $deletate-target-outer-try-unreachable ;; An inner try-delegate targets an outer try whose body type is unreachable @@ -1841,15 +2062,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $delegate-target-caller-none (type $1) - ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) - ;; STACKIR-OPT-NEXT: call $bar - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: call $baz - ;; STACKIR-OPT-NEXT: return - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: (call $bar) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (call $baz) + ;; STACKIR-OPT-NEXT: (return) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $delegate-target-caller-none ;; A try-delegate targets the caller whose type is none @@ -1879,18 +2101,19 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $multiple-delegates-target-caller-none (type $1) - ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) - ;; STACKIR-OPT-NEXT: call $bar - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) - ;; STACKIR-OPT-NEXT: call $bar - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: call $baz - ;; STACKIR-OPT-NEXT: return - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: (call $bar) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: (call $bar) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (call $baz) + ;; STACKIR-OPT-NEXT: (return) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $multiple-delegates-target-caller-none ;; Multiple try-delegates target the caller whose type is none @@ -1926,15 +2149,19 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $delegate-target-caller-concrete (type $2) (result i32) - ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_all_ref $__binaryen_delegate_caller_target0) - ;; STACKIR-OPT-NEXT: call $bar - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: return - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref) + ;; STACKIR-OPT-NEXT: (return + ;; STACKIR-OPT-NEXT: (block (result i32) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: (call $bar) + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $delegate-target-caller-concrete (result i32) ;; A try-delegate targets the caller whose type is concrete @@ -1974,27 +2201,29 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $delegate-nested-more (type $1) - ;; STACKIR-OPT-NEXT: block $outer3 - ;; STACKIR-OPT-NEXT: block $catch_all4 - ;; STACKIR-OPT-NEXT: try_table (catch_all $catch_all4) - ;; STACKIR-OPT-NEXT: block $l00 (result exnref) - ;; STACKIR-OPT-NEXT: block $outer1 - ;; STACKIR-OPT-NEXT: block $catch_all2 - ;; STACKIR-OPT-NEXT: try_table (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer1 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer3 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: unreachable - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer3 + ;; STACKIR-OPT-NEXT: (block $catch_all4 + ;; STACKIR-OPT-NEXT: (try_table (catch_all $catch_all4) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $l00 (result exnref) + ;; STACKIR-OPT-NEXT: (block $outer1 + ;; STACKIR-OPT-NEXT: (block $catch_all2 + ;; STACKIR-OPT-NEXT: (try_table (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l00) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (nop) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer3) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (nop) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $delegate-nested-more (try $l0 @@ -2035,22 +2264,23 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $delegate-target-outer-try-delegate (type $1) - ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) - ;; STACKIR-OPT-NEXT: block $outer2 - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) - ;; STACKIR-OPT-NEXT: block $l01 (result exnref) - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l01) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer2 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: unreachable - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: return - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref) + ;; STACKIR-OPT-NEXT: (block $outer2 + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $l01 (result exnref) + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l01) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (return) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $delegate-target-outer-try-delegate ;; An inner try-delegate targets an outer try-delegate that targets the @@ -2091,23 +2321,26 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $delegate-target-outer-try-delegate-concrete (type $2) (result i32) - ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) - ;; STACKIR-OPT-NEXT: block $outer2 (result i32) - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) - ;; STACKIR-OPT-NEXT: block $l01 (result exnref) - ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_all_ref $l01) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: i32.const 0 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer2 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: unreachable - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: return - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref) + ;; STACKIR-OPT-NEXT: (return + ;; STACKIR-OPT-NEXT: (block $outer2 (result i32) + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $l01 (result exnref) + ;; STACKIR-OPT-NEXT: (br $outer2 + ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch_all_ref $l01) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: (i32.const 0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $delegate-target-outer-try-delegate-concrete (result i32) ;; An inner try-delegate targets an outer try-delegate that targets the @@ -2141,13 +2374,18 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $throw_ref-in-resultless-block (type $2) (result i32) - ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: unreachable - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref) + ;; STACKIR-OPT-NEXT: (return + ;; STACKIR-OPT-NEXT: (block + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (unreachable) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $throw_ref-in-resultless-block (result i32) ;; When the function return type is concrete, try-delegate that targets the @@ -2186,18 +2424,18 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-delegate-within-catchless-try (type $1) - ;; STACKIR-OPT-NEXT: block $outer1 - ;; STACKIR-OPT-NEXT: try_table - ;; STACKIR-OPT-NEXT: block $l00 (result exnref) - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer1 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: unreachable - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer1 + ;; STACKIR-OPT-NEXT: (try_table + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $l00 (result exnref) + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l00) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-delegate-within-catchless-try (try $l0 @@ -2244,27 +2482,33 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-catch-rethrow-with-inner-delegate (type $1) ;; STACKIR-OPT-NEXT: (local $0 exnref) - ;; STACKIR-OPT-NEXT: block $outer2 - ;; STACKIR-OPT-NEXT: block $catch3 (result exnref) - ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-empty $catch3) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer2 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: block $outer1 - ;; STACKIR-OPT-NEXT: try_table - ;; STACKIR-OPT-NEXT: block $l10 (result exnref) - ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l10) - ;; STACKIR-OPT-NEXT: call $foo - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: br $outer1 - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: unreachable - ;; STACKIR-OPT-NEXT: end - ;; STACKIR-OPT-NEXT: throw_ref - ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: (block $outer2 + ;; STACKIR-OPT-NEXT: (local.set $0 + ;; STACKIR-OPT-NEXT: (block $catch3 (result exnref) + ;; STACKIR-OPT-NEXT: (try_table (catch_ref $e-empty $catch3) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer2) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (block + ;; STACKIR-OPT-NEXT: (block $outer1 + ;; STACKIR-OPT-NEXT: (try_table + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (block $l10 (result exnref) + ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l10) + ;; STACKIR-OPT-NEXT: (call $foo) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (br $outer1) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: (throw_ref + ;; STACKIR-OPT-NEXT: (local.get $0) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: ) ;; STACKIR-OPT-NEXT: ) (func $try-catch-rethrow-with-inner-delegate (try $l0 diff --git a/test/passes/O1_print-stack-ir.txt b/test/passes/O1_print-stack-ir.txt index 0a64713d378..d6cececfca8 100644 --- a/test/passes/O1_print-stack-ir.txt +++ b/test/passes/O1_print-stack-ir.txt @@ -28,25 +28,16 @@ (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) (func $stacky-help (param $0 i32) (result i32) - (i32.add - (call $stacky-help - (i32.const 0) - ) - (block (result i32) - (local.set $0 - (call $stacky-help - (i32.const 1) - ) - ) - (drop - (call $stacky-help - (i32.const 2) - ) - ) - (i32.eqz - (local.get $0) - ) - ) - ) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + local.set $0 + i32.const 2 + call $stacky-help + drop + local.get $0 + i32.eqz + i32.add ) ) diff --git a/test/passes/O2_precompute-propagate_print-stack-ir.txt b/test/passes/O2_precompute-propagate_print-stack-ir.txt index b0789141a81..119d1cafb71 100644 --- a/test/passes/O2_precompute-propagate_print-stack-ir.txt +++ b/test/passes/O2_precompute-propagate_print-stack-ir.txt @@ -15,10 +15,8 @@ (export "func" (func $func)) (func $func (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i64) (result i64) (local $4 i32) - (local.set $3 - (i64.const 2147483647) - ) - (nop) - (i64.const 2147483647) + i64.const 2147483647 + local.set $3 + i64.const 2147483647 ) ) diff --git a/test/passes/O2_print-stack-ir.txt b/test/passes/O2_print-stack-ir.txt index cdfccc3d467..d6cececfca8 100644 --- a/test/passes/O2_print-stack-ir.txt +++ b/test/passes/O2_print-stack-ir.txt @@ -2,23 +2,6 @@ (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) (func $stacky-help (param $0 i32) (result i32) - i32.const 0 - call $stacky-help - i32.const 1 - call $stacky-help - local.set $0 - i32.const 2 - call $stacky-help - drop - local.get $0 - i32.eqz - i32.add - ) -) -(module - (type $0 (func (param i32) (result i32))) - (export "stacky-help" (func $stacky-help)) - (func $stacky-help (; has Stack IR ;) (param $0 i32) (result i32) (i32.add (call $stacky-help (i32.const 0) @@ -41,3 +24,20 @@ ) ) ) +(module + (type $0 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (param $0 i32) (result i32) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + local.set $0 + i32.const 2 + call $stacky-help + drop + local.get $0 + i32.eqz + i32.add + ) +) diff --git a/test/passes/O3_print-stack-ir.txt b/test/passes/O3_print-stack-ir.txt index 569c49966ea..18aa4053fd9 100644 --- a/test/passes/O3_print-stack-ir.txt +++ b/test/passes/O3_print-stack-ir.txt @@ -2,21 +2,6 @@ (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) (func $stacky-help (param $0 i32) (result i32) - i32.const 0 - call $stacky-help - i32.const 1 - call $stacky-help - i32.const 2 - call $stacky-help - drop - i32.eqz - i32.add - ) -) -(module - (type $0 (func (param i32) (result i32))) - (export "stacky-help" (func $stacky-help)) - (func $stacky-help (; has Stack IR ;) (param $0 i32) (result i32) (i32.add (call $stacky-help (i32.const 0) @@ -39,3 +24,18 @@ ) ) ) +(module + (type $0 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (param $0 i32) (result i32) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + i32.const 2 + call $stacky-help + drop + i32.eqz + i32.add + ) +) diff --git a/test/passes/Os_print-stack-ir_all-features_disable-gc.txt b/test/passes/Os_print-stack-ir_all-features_disable-gc.txt index 569c49966ea..18aa4053fd9 100644 --- a/test/passes/Os_print-stack-ir_all-features_disable-gc.txt +++ b/test/passes/Os_print-stack-ir_all-features_disable-gc.txt @@ -2,21 +2,6 @@ (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) (func $stacky-help (param $0 i32) (result i32) - i32.const 0 - call $stacky-help - i32.const 1 - call $stacky-help - i32.const 2 - call $stacky-help - drop - i32.eqz - i32.add - ) -) -(module - (type $0 (func (param i32) (result i32))) - (export "stacky-help" (func $stacky-help)) - (func $stacky-help (; has Stack IR ;) (param $0 i32) (result i32) (i32.add (call $stacky-help (i32.const 0) @@ -39,3 +24,18 @@ ) ) ) +(module + (type $0 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (param $0 i32) (result i32) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + i32.const 2 + call $stacky-help + drop + i32.eqz + i32.add + ) +) diff --git a/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt b/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt index c9cacca3978..2eb5aa7da4e 100644 --- a/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt +++ b/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt @@ -1,23 +1,6 @@ (module (type $0 (func (param i64))) (func $0 (param $var$0 i64) - block $label$1 - block $label$2 - loop $label$3 - block $label$4 - unreachable - end - unreachable - end - unreachable - end - unreachable - end - ) -) -(module - (type $0 (func (param i64))) - (func $0 (; has Stack IR ;) (param $var$0 i64) (block $label$1 (br_if $label$1 (block $label$2 @@ -34,3 +17,20 @@ ) ) ) +(module + (type $0 (func (param i64))) + (func $0 (param $var$0 i64) + block $label$1 + block $label$2 + loop $label$3 + block $label$4 + unreachable + end + unreachable + end + unreachable + end + unreachable + end + ) +) From a820011293c38afb79c7f7b8abb04610296ab9c0 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:56:18 -0700 Subject: [PATCH 37/77] Revert "builds" This reverts commit 78ee7fd197fdc4345f8cfe8b0d1b79a3499b5d59. --- src/wasm-binary.h | 1 - src/wasm/wasm-binary.cpp | 56 +- test/lit/passes/optimize-stack-ir.wast | 1308 ++++++---------- test/lit/passes/stack-ir-eh.wast | 41 +- test/lit/passes/stack-ir-non-nullable.wast | 762 ++++----- test/lit/passes/translate-to-new-eh.wast | 1380 +++++++---------- test/passes/O1_print-stack-ir.txt | 31 +- ...O2_precompute-propagate_print-stack-ir.txt | 8 +- test/passes/O2_print-stack-ir.txt | 34 +- test/passes/O3_print-stack-ir.txt | 30 +- ...print-stack-ir_all-features_disable-gc.txt | 30 +- ...d-brs_generate-stack-ir_print-stack-ir.txt | 34 +- 12 files changed, 1413 insertions(+), 2302 deletions(-) diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 4ec7e335249..310b251c177 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1314,7 +1314,6 @@ class WasmBinaryWriter { void writeFunctionSignatures(); void writeExpression(Expression* curr); - void prepareFunctions(); void writeFunctions(); void writeStrings(); void writeGlobals(); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 811366f99a7..86bf846c511 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -69,7 +69,6 @@ void WasmBinaryWriter::write() { writeStart(); writeElementSegments(); writeDataCount(); - prepareFunctions(); writeFunctions(); writeDataSegments(); if (debugInfo || emitModuleName) { @@ -371,42 +370,6 @@ void WasmBinaryWriter::writeImports() { finishSection(start); } -void WasmBinaryWriter::prepareFunctions() { - if (!options.generateStackIR) { - return; - } - - // Generate StackIR for functions in parallel, and optimize if requested. - struct StackIRPass - : public WalkerPass> { - bool isFunctionParallel() override { return true; } - - std::unique_ptr create() override { - return std::make_unique(); - } - - void doWalkFunction(Function* func) { - StackIRGenerator stackIRGen(*getModule(), func); - stackIRGen.write(); - func->stackIR = std::make_unique(); - func->stackIR->swap(stackIRGen.getStackIR()); - - auto& options = getPassOptions(); - if (options.optimizeStackIR) { - StackIROptimizer optimizer(func, options, getModule()->features); - optimizer.run(); - } - } - }; - - PassRunner runner(wasm, options); - StackIRPass().run(&runner, wasm); - - if (options.printStackIR) { - printStackIR(std::cout, wasm); - } -} - void WasmBinaryWriter::writeFunctionSignatures() { if (importInfo->getNumDefinedFunctions() == 0) { return; @@ -440,7 +403,24 @@ void WasmBinaryWriter::writeFunctions() { size_t sizePos = writeU32LEBPlaceholder(); size_t start = o.size(); BYN_TRACE("writing" << func->name << std::endl); - // Emit Stack IR if present. + + if (options.generateStackIR) { + StackIRGenerator stackIRGen(*getModule(), func); + stackIRGen.write(); + func->stackIR = std::make_unique(); + func->stackIR->swap(stackIRGen.getStackIR()); + + if (options.optimizeStackIR) { + StackIROptimizer optimizer(func, options, wasm->features); + optimizer.run(); + } + + if (options.printStackIR) { // from a wasm-opt commandline flag + printStackIR(std::cout, wasm); + } + } + + // Emit Stack IR if present, and if we can if (func->stackIR) { BYN_TRACE("write Stack IR\n"); StackIRToBinaryWriter writer(*this, o, func, sourceMap, DWARF); diff --git a/test/lit/passes/optimize-stack-ir.wast b/test/lit/passes/optimize-stack-ir.wast index bd744524ed2..123be3afb8a 100644 --- a/test/lit/passes/optimize-stack-ir.wast +++ b/test/lit/passes/optimize-stack-ir.wast @@ -91,59 +91,39 @@ ;; CHECK: (func $importedDoubles (type $4) (result f64) ;; CHECK-NEXT: (local $temp f64) - ;; CHECK-NEXT: (block $topmost (result f64) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.neg - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (i32.const 16) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.neg - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (i32.const 24) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (br $topmost - ;; CHECK-NEXT: (f64.const -3.4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (f64.gt - ;; CHECK-NEXT: (f64.load - ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (br $topmost - ;; CHECK-NEXT: (f64.const 5.6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 1.2) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: block $topmost (result f64) + ;; CHECK-NEXT: i32.const 8 + ;; CHECK-NEXT: f64.load + ;; CHECK-NEXT: i32.const 16 + ;; CHECK-NEXT: f64.load + ;; CHECK-NEXT: f64.add + ;; CHECK-NEXT: i32.const 16 + ;; CHECK-NEXT: f64.load + ;; CHECK-NEXT: f64.neg + ;; CHECK-NEXT: f64.add + ;; CHECK-NEXT: i32.const 8 + ;; CHECK-NEXT: f64.load + ;; CHECK-NEXT: f64.neg + ;; CHECK-NEXT: f64.add + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: i32.const 24 + ;; CHECK-NEXT: i32.load + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: i32.gt_s + ;; CHECK-NEXT: if + ;; CHECK-NEXT: f64.const -3.4 + ;; CHECK-NEXT: br $topmost + ;; CHECK-NEXT: end + ;; CHECK-NEXT: i32.const 32 + ;; CHECK-NEXT: f64.load + ;; CHECK-NEXT: f64.const 0 + ;; CHECK-NEXT: f64.gt + ;; CHECK-NEXT: if + ;; CHECK-NEXT: f64.const 5.6 + ;; CHECK-NEXT: br $topmost + ;; CHECK-NEXT: end + ;; CHECK-NEXT: f64.const 1.2 + ;; CHECK-NEXT: end ;; CHECK-NEXT: ) (func $importedDoubles (type $4) (result f64) (local $temp f64) @@ -206,53 +186,37 @@ ;; CHECK-NEXT: (local $t f64) ;; CHECK-NEXT: (local $Int f64) ;; CHECK-NEXT: (local $Double i32) - ;; CHECK-NEXT: (block $topmost (result f64) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (f64.gt - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (br $topmost - ;; CHECK-NEXT: (f64.const 1.2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (f64.gt - ;; CHECK-NEXT: (local.get $Int) - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (br $topmost - ;; CHECK-NEXT: (f64.const -3.4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $Double) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (br $topmost - ;; CHECK-NEXT: (f64.const 5.6) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (f64.lt - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (br $topmost - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: block $topmost (result f64) + ;; CHECK-NEXT: local.get $x + ;; CHECK-NEXT: f64.const 0 + ;; CHECK-NEXT: f64.gt + ;; CHECK-NEXT: if + ;; CHECK-NEXT: f64.const 1.2 + ;; CHECK-NEXT: br $topmost + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $Int + ;; CHECK-NEXT: f64.const 0 + ;; CHECK-NEXT: f64.gt + ;; CHECK-NEXT: if + ;; CHECK-NEXT: f64.const -3.4 + ;; CHECK-NEXT: br $topmost + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $Double + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: i32.gt_s + ;; CHECK-NEXT: if + ;; CHECK-NEXT: f64.const 5.6 + ;; CHECK-NEXT: br $topmost + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $x + ;; CHECK-NEXT: local.get $y + ;; CHECK-NEXT: f64.lt + ;; CHECK-NEXT: if + ;; CHECK-NEXT: local.get $x + ;; CHECK-NEXT: br $topmost + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $y + ;; CHECK-NEXT: end ;; CHECK-NEXT: ) (func $doubleCompares (type $FUNCSIG$ddd) (param $x f64) (param $y f64) (result f64) (local $t f64) @@ -309,10 +273,9 @@ ;; CHECK: (func $intOps (type $5) (result i32) ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $x + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: i32.eq ;; CHECK-NEXT: ) (func $intOps (type $5) (result i32) (local $x i32) @@ -323,15 +286,12 @@ ) ;; CHECK: (func $hexLiterals (type $FUNCSIG$v) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (i32.const 313249263) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -19088752) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: i32.const 313249263 + ;; CHECK-NEXT: i32.add + ;; CHECK-NEXT: i32.const -19088752 + ;; CHECK-NEXT: i32.add + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $hexLiterals (type $FUNCSIG$v) (drop @@ -347,26 +307,17 @@ ;; CHECK: (func $conversions (type $FUNCSIG$v) ;; CHECK-NEXT: (local $i i32) ;; CHECK-NEXT: (local $d f64) - ;; CHECK-NEXT: (block $block0 - ;; CHECK-NEXT: (local.set $i - ;; CHECK-NEXT: (call $f64-to-int - ;; CHECK-NEXT: (local.get $d) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $d - ;; CHECK-NEXT: (f64.convert_i32_s - ;; CHECK-NEXT: (local.get $i) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $d - ;; CHECK-NEXT: (f64.convert_i32_u - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $i) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $d + ;; CHECK-NEXT: call $f64-to-int + ;; CHECK-NEXT: local.set $i + ;; CHECK-NEXT: local.get $i + ;; CHECK-NEXT: f64.convert_i32_s + ;; CHECK-NEXT: local.set $d + ;; CHECK-NEXT: local.get $i + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: i32.shr_u + ;; CHECK-NEXT: f64.convert_i32_u + ;; CHECK-NEXT: local.set $d ;; CHECK-NEXT: ) (func $conversions (type $FUNCSIG$v) (local $i i32) @@ -395,22 +346,14 @@ ;; CHECK: (func $seq (type $FUNCSIG$v) ;; CHECK-NEXT: (local $J f64) - ;; CHECK-NEXT: (local.set $J - ;; CHECK-NEXT: (f64.sub - ;; CHECK-NEXT: (block $block0 (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.const 0.1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 5.1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block1 (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f64.const 3.2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (f64.const 4.2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: f64.const 0.1 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: f64.const 5.1 + ;; CHECK-NEXT: f64.const 3.2 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: f64.const 4.2 + ;; CHECK-NEXT: f64.sub + ;; CHECK-NEXT: local.set $J ;; CHECK-NEXT: ) (func $seq (type $FUNCSIG$v) (local $J f64) @@ -433,90 +376,65 @@ ) ;; CHECK: (func $switcher (type $6) (param $x i32) (result i32) - ;; CHECK-NEXT: (block $topmost (result i32) - ;; CHECK-NEXT: (block $switch$0 - ;; CHECK-NEXT: (block $switch-default$3 - ;; CHECK-NEXT: (block $switch-case$2 - ;; CHECK-NEXT: (block $switch-case$1 - ;; CHECK-NEXT: (br_table $switch-case$1 $switch-case$2 $switch-default$3 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $topmost - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $topmost - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $switch$4 - ;; CHECK-NEXT: (block $switch-default$7 - ;; CHECK-NEXT: (block $switch-case$6 - ;; CHECK-NEXT: (block $switch-case$5 - ;; CHECK-NEXT: (br_table $switch-case$6 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-case$5 $switch-default$7 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $topmost - ;; CHECK-NEXT: (i32.const 121) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $topmost - ;; CHECK-NEXT: (i32.const 51) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $label$break$Lout - ;; CHECK-NEXT: (block $switch-default$16 - ;; CHECK-NEXT: (block $switch-case$15 - ;; CHECK-NEXT: (block $switch-case$12 - ;; CHECK-NEXT: (block $switch-case$9 - ;; CHECK-NEXT: (block $switch-case$8 - ;; CHECK-NEXT: (br_table $switch-case$15 $switch-default$16 $switch-default$16 $switch-case$12 $switch-default$16 $switch-default$16 $switch-default$16 $switch-default$16 $switch-case$9 $switch-default$16 $switch-case$8 $switch-default$16 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$Lout) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$Lout) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $while-out$10 - ;; CHECK-NEXT: (loop $while-in$11 - ;; CHECK-NEXT: (block $block1 - ;; CHECK-NEXT: (br $while-out$10) - ;; CHECK-NEXT: (br $while-in$11) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$Lout) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $while-out$13 - ;; CHECK-NEXT: (loop $while-in$14 - ;; CHECK-NEXT: (block $block3 - ;; CHECK-NEXT: (br $label$break$Lout) - ;; CHECK-NEXT: (br $while-in$14) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $label$break$Lout) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: block $topmost (result i32) + ;; CHECK-NEXT: block $switch-default$3 + ;; CHECK-NEXT: block $switch-case$2 + ;; CHECK-NEXT: block $switch-case$1 + ;; CHECK-NEXT: local.get $x + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: i32.sub + ;; CHECK-NEXT: br_table $switch-case$1 $switch-case$2 $switch-default$3 + ;; CHECK-NEXT: end + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: br $topmost + ;; CHECK-NEXT: end + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: br $topmost + ;; CHECK-NEXT: end + ;; CHECK-NEXT: block $switch-default$7 + ;; CHECK-NEXT: block $switch-case$6 + ;; CHECK-NEXT: block $switch-case$5 + ;; CHECK-NEXT: local.get $x + ;; CHECK-NEXT: i32.const 5 + ;; CHECK-NEXT: i32.sub + ;; CHECK-NEXT: br_table $switch-case$6 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-default$7 $switch-case$5 $switch-default$7 + ;; CHECK-NEXT: end + ;; CHECK-NEXT: i32.const 121 + ;; CHECK-NEXT: br $topmost + ;; CHECK-NEXT: end + ;; CHECK-NEXT: i32.const 51 + ;; CHECK-NEXT: br $topmost + ;; CHECK-NEXT: end + ;; CHECK-NEXT: block $label$break$Lout + ;; CHECK-NEXT: block $switch-default$16 + ;; CHECK-NEXT: block $switch-case$15 + ;; CHECK-NEXT: block $switch-case$12 + ;; CHECK-NEXT: block $switch-case$9 + ;; CHECK-NEXT: block $switch-case$8 + ;; CHECK-NEXT: local.get $x + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: i32.sub + ;; CHECK-NEXT: br_table $switch-case$15 $switch-default$16 $switch-default$16 $switch-case$12 $switch-default$16 $switch-default$16 $switch-default$16 $switch-default$16 $switch-case$9 $switch-default$16 $switch-case$8 $switch-default$16 + ;; CHECK-NEXT: end + ;; CHECK-NEXT: br $label$break$Lout + ;; CHECK-NEXT: end + ;; CHECK-NEXT: br $label$break$Lout + ;; CHECK-NEXT: end + ;; CHECK-NEXT: block $while-out$10 + ;; CHECK-NEXT: loop $while-in$11 + ;; CHECK-NEXT: br $while-out$10 + ;; CHECK-NEXT: end + ;; CHECK-NEXT: unreachable + ;; CHECK-NEXT: end + ;; CHECK-NEXT: end + ;; CHECK-NEXT: loop $while-in$14 + ;; CHECK-NEXT: br $label$break$Lout + ;; CHECK-NEXT: end + ;; CHECK-NEXT: unreachable + ;; CHECK-NEXT: end + ;; CHECK-NEXT: end + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: end ;; CHECK-NEXT: ) (func $switcher (type $6) (param $x i32) (result i32) (block $topmost (result i32) @@ -606,9 +524,9 @@ ) ;; CHECK: (func $blocker (type $FUNCSIG$v) - ;; CHECK-NEXT: (block $label$break$L - ;; CHECK-NEXT: (br $label$break$L) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: block $label$break$L + ;; CHECK-NEXT: br $label$break$L + ;; CHECK-NEXT: end ;; CHECK-NEXT: ) (func $blocker (type $FUNCSIG$v) (block $label$break$L @@ -617,10 +535,9 @@ ) ;; CHECK: (func $frem (type $4) (result f64) - ;; CHECK-NEXT: (call $f64-rem - ;; CHECK-NEXT: (f64.const 5.5) - ;; CHECK-NEXT: (f64.const 1.2) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: f64.const 5.5 + ;; CHECK-NEXT: f64.const 1.2 + ;; CHECK-NEXT: call $f64-rem ;; CHECK-NEXT: ) (func $frem (type $4) (result f64) (call $f64-rem @@ -631,18 +548,11 @@ ;; CHECK: (func $big_uint_div_u (type $5) (result i32) ;; CHECK-NEXT: (local $x i32) - ;; CHECK-NEXT: (block $topmost (result i32) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.div_u - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const -1 + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: i32.div_u + ;; CHECK-NEXT: i32.const -1 + ;; CHECK-NEXT: i32.and ;; CHECK-NEXT: ) (func $big_uint_div_u (type $5) (result i32) (local $x i32) @@ -663,28 +573,19 @@ ;; CHECK: (func $fr (type $FUNCSIG$vf) (param $x f32) ;; CHECK-NEXT: (local $y f32) ;; CHECK-NEXT: (local $z f64) - ;; CHECK-NEXT: (block $block0 - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.demote_f64 - ;; CHECK-NEXT: (local.get $z) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $y) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $z + ;; CHECK-NEXT: f32.demote_f64 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $y + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: f32.const 5 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: f32.const 0 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: f32.const 5 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: f32.const 0 + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $fr (type $FUNCSIG$vf) (param $x f32) (local $y f32) @@ -714,7 +615,7 @@ ) ;; CHECK: (func $negZero (type $4) (result f64) - ;; CHECK-NEXT: (f64.const -0) + ;; CHECK-NEXT: f64.const -0 ;; CHECK-NEXT: ) (func $negZero (type $4) (result f64) (f64.const -0) @@ -725,36 +626,23 @@ ;; CHECK-NEXT: (local $y f64) ;; CHECK-NEXT: (local $z f32) ;; CHECK-NEXT: (local $asm2wasm_i32_temp i32) - ;; CHECK-NEXT: (block $block0 - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (block $block1 (result i32) - ;; CHECK-NEXT: (local.set $asm2wasm_i32_temp - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $asm2wasm_i32_temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $asm2wasm_i32_temp) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $asm2wasm_i32_temp) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $y - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (f64.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $z - ;; CHECK-NEXT: (f32.abs - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: local.set $asm2wasm_i32_temp + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: local.get $asm2wasm_i32_temp + ;; CHECK-NEXT: i32.sub + ;; CHECK-NEXT: local.get $asm2wasm_i32_temp + ;; CHECK-NEXT: local.get $asm2wasm_i32_temp + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: i32.lt_s + ;; CHECK-NEXT: select + ;; CHECK-NEXT: local.set $x + ;; CHECK-NEXT: f64.const 0 + ;; CHECK-NEXT: f64.abs + ;; CHECK-NEXT: local.set $y + ;; CHECK-NEXT: f32.const 0 + ;; CHECK-NEXT: f32.abs + ;; CHECK-NEXT: local.set $z ;; CHECK-NEXT: ) (func $abs (type $FUNCSIG$v) (local $x i32) @@ -795,23 +683,14 @@ ;; CHECK: (func $neg (type $FUNCSIG$v) ;; CHECK-NEXT: (local $x f32) - ;; CHECK-NEXT: (block $block0 - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (f32.neg - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (call_indirect $table (type $FUNCSIG$vf) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $x + ;; CHECK-NEXT: f32.neg + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: i32.const 7 + ;; CHECK-NEXT: i32.and + ;; CHECK-NEXT: i32.const 8 + ;; CHECK-NEXT: i32.add + ;; CHECK-NEXT: call_indirect $table (type $FUNCSIG$vf) ;; CHECK-NEXT: ) (func $neg (type $FUNCSIG$v) (local $x f32) @@ -835,16 +714,13 @@ ) ;; CHECK: (func $cneg (type $FUNCSIG$vf) (param $x f32) - ;; CHECK-NEXT: (call_indirect $table (type $FUNCSIG$vf) - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (i32.const 7) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $x + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: i32.const 7 + ;; CHECK-NEXT: i32.and + ;; CHECK-NEXT: i32.const 8 + ;; CHECK-NEXT: i32.add + ;; CHECK-NEXT: call_indirect $table (type $FUNCSIG$vf) ;; CHECK-NEXT: ) (func $cneg (type $FUNCSIG$vf) (param $x f32) (call_indirect (type $FUNCSIG$vf) @@ -861,15 +737,12 @@ ;; CHECK: (func $___syscall_ret (type $FUNCSIG$v) ;; CHECK-NEXT: (local $$0 i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.get $$0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const -4096) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $$0 + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: i32.shr_u + ;; CHECK-NEXT: i32.const -4096 + ;; CHECK-NEXT: i32.gt_u + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $___syscall_ret (type $FUNCSIG$v) (local $$0 i32) @@ -885,27 +758,24 @@ ) ;; CHECK: (func $z (type $FUNCSIG$v) - ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $z (type $FUNCSIG$v) (nop) ) ;; CHECK: (func $w (type $FUNCSIG$v) - ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $w (type $FUNCSIG$v) (nop) ) ;; CHECK: (func $block_and_after (type $5) (result i32) - ;; CHECK-NEXT: (block $waka - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $waka) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: block $waka + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: br $waka + ;; CHECK-NEXT: end + ;; CHECK-NEXT: i32.const 0 ;; CHECK-NEXT: ) (func $block_and_after (type $5) (result i32) (block $waka @@ -918,12 +788,11 @@ ) ;; CHECK: (func $loop-roundtrip (type $7) (param $0 f64) (result f64) - ;; CHECK-NEXT: (loop $loop-in1 (result f64) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: loop $loop-in1 (result f64) + ;; CHECK-NEXT: local.get $0 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $0 + ;; CHECK-NEXT: end ;; CHECK-NEXT: ) (func $loop-roundtrip (type $7) (param $0 f64) (result f64) (loop $loop-in1 (result f64) @@ -935,17 +804,16 @@ ) ;; CHECK: (func $big-i64 (type $8) (result i64) - ;; CHECK-NEXT: (i64.const -9218868437227405313) + ;; CHECK-NEXT: i64.const -9218868437227405313 ;; CHECK-NEXT: ) (func $big-i64 (type $8) (result i64) (i64.const -9218868437227405313) ) ;; CHECK: (func $i64-store32 (type $9) (param $0 i32) (param $1 i64) - ;; CHECK-NEXT: (i64.store32 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $0 + ;; CHECK-NEXT: local.get $1 + ;; CHECK-NEXT: i64.store32 ;; CHECK-NEXT: ) (func $i64-store32 (type $9) (param $0 i32) (param $1 i64) (i64.store32 @@ -955,25 +823,18 @@ ) ;; CHECK: (func $return-unreachable (type $5) (result i32) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: return ;; CHECK-NEXT: ) (func $return-unreachable (result i32) (return (i32.const 1)) ) ;; CHECK: (func $unreachable-block (type $5) (result i32) - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: return ;; CHECK-NEXT: ) (func $unreachable-block (result i32) (f64.abs @@ -985,12 +846,10 @@ ) ;; CHECK: (func $unreachable-block-toplevel (type $5) (result i32) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: return ;; CHECK-NEXT: ) (func $unreachable-block-toplevel (result i32) (block ;; note no type - valid in binaryen IR, in wasm must be i32 @@ -1000,13 +859,8 @@ ) ;; CHECK: (func $unreachable-block0 (type $5) (result i32) - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: return ;; CHECK-NEXT: ) (func $unreachable-block0 (result i32) (f64.abs @@ -1017,9 +871,8 @@ ) ;; CHECK: (func $unreachable-block0-toplevel (type $5) (result i32) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: return ;; CHECK-NEXT: ) (func $unreachable-block0-toplevel (result i32) (block ;; note no type - valid in binaryen IR, in wasm must be i32 @@ -1028,13 +881,12 @@ ) ;; CHECK: (func $unreachable-block-with-br (type $5) (result i32) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $block) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: block $block + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: br $block + ;; CHECK-NEXT: end + ;; CHECK-NEXT: i32.const 1 ;; CHECK-NEXT: ) (func $unreachable-block-with-br (result i32) (block $block ;; unreachable type due to last element having that type, but the block is exitable @@ -1045,21 +897,15 @@ ) ;; CHECK: (func $unreachable-if (type $5) (result i32) - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 3 + ;; CHECK-NEXT: if + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: return + ;; CHECK-NEXT: else + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: return + ;; CHECK-NEXT: end + ;; CHECK-NEXT: unreachable ;; CHECK-NEXT: ) (func $unreachable-if (result i32) (f64.abs @@ -1076,19 +922,15 @@ ) ;; CHECK: (func $unreachable-if-toplevel (type $5) (result i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 3 + ;; CHECK-NEXT: if + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: return + ;; CHECK-NEXT: else + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: return + ;; CHECK-NEXT: end + ;; CHECK-NEXT: unreachable ;; CHECK-NEXT: ) (func $unreachable-if-toplevel (result i32) (if ;; note no type - valid in binaryen IR, in wasm must be i32 @@ -1103,14 +945,11 @@ ) ;; CHECK: (func $unreachable-loop (type $5) (result i32) - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (loop - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: loop + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: return + ;; CHECK-NEXT: end + ;; CHECK-NEXT: unreachable ;; CHECK-NEXT: ) (func $unreachable-loop (result i32) (f64.abs @@ -1122,13 +961,11 @@ ) ;; CHECK: (func $unreachable-loop0 (type $5) (result i32) - ;; CHECK-NEXT: (f64.abs - ;; CHECK-NEXT: (loop - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: loop + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: return + ;; CHECK-NEXT: end + ;; CHECK-NEXT: unreachable ;; CHECK-NEXT: ) (func $unreachable-loop0 (result i32) (f64.abs @@ -1139,12 +976,11 @@ ) ;; CHECK: (func $unreachable-loop-toplevel (type $5) (result i32) - ;; CHECK-NEXT: (loop - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: loop + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: return + ;; CHECK-NEXT: end + ;; CHECK-NEXT: unreachable ;; CHECK-NEXT: ) (func $unreachable-loop-toplevel (result i32) (loop ;; note no type - valid in binaryen IR, in wasm must be i32 @@ -1154,11 +990,11 @@ ) ;; CHECK: (func $unreachable-loop0-toplevel (type $5) (result i32) - ;; CHECK-NEXT: (loop - ;; CHECK-NEXT: (return - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: loop + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: return + ;; CHECK-NEXT: end + ;; CHECK-NEXT: unreachable ;; CHECK-NEXT: ) (func $unreachable-loop0-toplevel (result i32) (loop ;; note no type - valid in binaryen IR, in wasm must be i32 @@ -1167,81 +1003,7 @@ ) ;; CHECK: (func $unreachable-ifs (type $FUNCSIG$v) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: unreachable ;; CHECK-NEXT: ) (func $unreachable-ifs (if (unreachable) (then (nop))) @@ -1257,18 +1019,11 @@ ) ;; CHECK: (func $unreachable-if-arm (type $FUNCSIG$v) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: if + ;; CHECK-NEXT: else + ;; CHECK-NEXT: unreachable + ;; CHECK-NEXT: end ;; CHECK-NEXT: ) (func $unreachable-if-arm (if @@ -1291,17 +1046,11 @@ ;; CHECK: (func $local-to-stack (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $local-to-stack - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: call $local-to-stack + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $local-to-stack (param $x i32) (result i32) (local $temp i32) @@ -1312,19 +1061,12 @@ ;; CHECK: (func $local-to-stack-1 (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $local-to-stack - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: call $local-to-stack + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: i32.eqz ;; CHECK-NEXT: ) (func $local-to-stack-1 (param $x i32) (result i32) (local $temp i32) @@ -1337,20 +1079,13 @@ ;; CHECK: (func $local-to-stack-1b (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $local-to-stack - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: call $local-to-stack + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: i32.const 3 + ;; CHECK-NEXT: i32.add ;; CHECK-NEXT: ) (func $local-to-stack-1b (param $x i32) (result i32) (local $temp i32) @@ -1364,20 +1099,15 @@ ;; CHECK: (func $local-to-stack-1c-no (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $local-to-stack - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: call $local-to-stack + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: i32.const 3 + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: i32.add ;; CHECK-NEXT: ) (func $local-to-stack-1c-no (param $x i32) (result i32) (local $temp i32) @@ -1391,20 +1121,15 @@ ;; CHECK: (func $local-to-stack-2-no (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $local-to-stack - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: call $local-to-stack + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: i32.add ;; CHECK-NEXT: ) (func $local-to-stack-2-no (param $x i32) (result i32) (local $temp i32) @@ -1418,29 +1143,20 @@ ;; CHECK: (func $local-to-stack-3-no (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $local-to-stack - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $local-to-stack - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: if + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: else + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: call $local-to-stack + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: end + ;; CHECK-NEXT: i32.const 3 + ;; CHECK-NEXT: call $local-to-stack + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $temp ;; CHECK-NEXT: ) (func $local-to-stack-3-no (param $x i32) (result i32) (local $temp i32) @@ -1459,30 +1175,17 @@ ;; CHECK: (func $local-to-stack-multi-4 (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp1 i32) ;; CHECK-NEXT: (local $temp2 i32) - ;; CHECK-NEXT: (local.set $temp1 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp1 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp1) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: i32.const 3 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: i32.const 4 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $local-to-stack-multi-4 (param $x i32) (result i32) (local $temp1 i32) @@ -1498,30 +1201,17 @@ ;; CHECK: (func $local-to-stack-multi-5 (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp1 i32) ;; CHECK-NEXT: (local $temp2 i32) - ;; CHECK-NEXT: (local.set $temp1 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp2 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp2) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: i32.const 3 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: i32.const 4 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $local-to-stack-multi-5 (param $x i32) (result i32) (local $temp1 i32) @@ -1537,33 +1227,21 @@ ;; CHECK: (func $local-to-stack-multi-6-justone (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp1 i32) ;; CHECK-NEXT: (local $temp2 i32) - ;; CHECK-NEXT: (local.set $temp1 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp2 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $temp2) - ;; CHECK-NEXT: (local.get $temp2) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: i32.const 3 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: local.set $temp2 + ;; CHECK-NEXT: i32.const 4 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $temp2 + ;; CHECK-NEXT: local.get $temp2 + ;; CHECK-NEXT: i32.add ;; CHECK-NEXT: ) (func $local-to-stack-multi-6-justone (param $x i32) (result i32) (local $temp1 i32) @@ -1582,33 +1260,21 @@ ;; CHECK: (func $local-to-stack-multi-7-justone (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp1 i32) ;; CHECK-NEXT: (local $temp2 i32) - ;; CHECK-NEXT: (local.set $temp1 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $temp1) - ;; CHECK-NEXT: (local.get $temp1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp2 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp2) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: local.set $temp1 + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $temp1 + ;; CHECK-NEXT: local.get $temp1 + ;; CHECK-NEXT: i32.add + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: i32.const 3 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: i32.const 4 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $local-to-stack-multi-7-justone (param $x i32) (result i32) (local $temp1 i32) @@ -1629,25 +1295,16 @@ ;; CHECK: (func $local-to-stack-overlapping-multi-8-no (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp1 i32) ;; CHECK-NEXT: (local $temp2 i32) - ;; CHECK-NEXT: (local.set $temp1 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp2 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $temp2) - ;; CHECK-NEXT: (local.get $temp1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: local.set $temp1 + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: i32.const 3 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $temp1 + ;; CHECK-NEXT: i32.add ;; CHECK-NEXT: ) (func $local-to-stack-overlapping-multi-8-no (param $x i32) (result i32) (local $temp1 i32) @@ -1664,25 +1321,14 @@ ;; CHECK: (func $local-to-stack-overlapping-multi-9-yes (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp1 i32) ;; CHECK-NEXT: (local $temp2 i32) - ;; CHECK-NEXT: (local.set $temp1 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp2 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $temp1) - ;; CHECK-NEXT: (local.get $temp2) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: i32.const 3 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: i32.add ;; CHECK-NEXT: ) (func $local-to-stack-overlapping-multi-9-yes (param $x i32) (result i32) (local $temp1 i32) @@ -1699,39 +1345,21 @@ ;; CHECK: (func $local-to-stack-through-control-flow (type $FUNCSIG$v) ;; CHECK-NEXT: (local $temp1 i32) ;; CHECK-NEXT: (local $temp2 i32) - ;; CHECK-NEXT: (local.set $temp2 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp1 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (nop) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp1 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (br $block) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp2) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: if + ;; CHECK-NEXT: end + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: block $block + ;; CHECK-NEXT: br $block + ;; CHECK-NEXT: end + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $local-to-stack-through-control-flow (local $temp1 i32) @@ -1748,29 +1376,16 @@ ;; CHECK: (func $local-to-stack-in-control-flow (type $FUNCSIG$v) ;; CHECK-NEXT: (local $temp1 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp1 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp1 - ;; CHECK-NEXT: (call $local-to-stack-multi-4 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: if + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: else + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $local-to-stack-multi-4 + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: end ;; CHECK-NEXT: ) (func $local-to-stack-in-control-flow (local $temp1 i32) @@ -1792,26 +1407,15 @@ ;; CHECK: (func $remove-block (type $6) (param $x i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (call $remove-block - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (call $remove-block - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call $remove-block - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: call $remove-block + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: call $remove-block + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: call $remove-block + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: i32.eqz + ;; CHECK-NEXT: i32.add ;; CHECK-NEXT: ) (func $remove-block (param $x i32) (result i32) (local $temp i32) @@ -1830,17 +1434,13 @@ ;; CHECK: (func $tuple-local2stack (type $FUNCSIG$v) ;; CHECK-NEXT: (local $pair (tuple f32 i32)) ;; CHECK-NEXT: (local $f32 f32) - ;; CHECK-NEXT: (local.set $pair - ;; CHECK-NEXT: (tuple.make 2 - ;; CHECK-NEXT: (f32.const 0) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $f32 - ;; CHECK-NEXT: (tuple.extract 2 0 - ;; CHECK-NEXT: (local.get $pair) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: f32.const 0 + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: tuple.make 2 + ;; CHECK-NEXT: local.set $pair + ;; CHECK-NEXT: local.get $pair + ;; CHECK-NEXT: tuple.extract 2 0 + ;; CHECK-NEXT: local.set $f32 ;; CHECK-NEXT: ) (func $tuple-local2stack (local $pair (tuple f32 i32)) diff --git a/test/lit/passes/stack-ir-eh.wast b/test/lit/passes/stack-ir-eh.wast index 86895ddd431..e06e5e5172d 100644 --- a/test/lit/passes/stack-ir-eh.wast +++ b/test/lit/passes/stack-ir-eh.wast @@ -11,28 +11,25 @@ (func $foo) ;; CHECK: (func $test (type $0) - ;; CHECK-NEXT: (block $outer - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block $l-catch (result i32) - ;; CHECK-NEXT: (tuple.drop 2 - ;; CHECK-NEXT: (block $l-catch-ref (type $1) (result i32 exnref) - ;; CHECK-NEXT: (block $l-catch-all - ;; CHECK-NEXT: (throw_ref - ;; CHECK-NEXT: (block $l-catch-all-ref (result exnref) - ;; CHECK-NEXT: (try_table (catch $e-i32 $l-catch) (catch_ref $e-i32 $l-catch-ref) (catch_all $l-catch-all) (catch_all_ref $l-catch-all-ref) - ;; CHECK-NEXT: (call $foo) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $outer) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $outer) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $outer) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: block $outer + ;; CHECK-NEXT: block $l-catch (result i32) + ;; CHECK-NEXT: block $l-catch-ref (type $1) (result i32 exnref) + ;; CHECK-NEXT: block $l-catch-all + ;; CHECK-NEXT: block $l-catch-all-ref (result exnref) + ;; CHECK-NEXT: try_table (catch $e-i32 $l-catch) (catch_ref $e-i32 $l-catch-ref) (catch_all $l-catch-all) (catch_all_ref $l-catch-all-ref) + ;; CHECK-NEXT: call $foo + ;; CHECK-NEXT: end + ;; CHECK-NEXT: br $outer + ;; CHECK-NEXT: end + ;; CHECK-NEXT: throw_ref + ;; CHECK-NEXT: end + ;; CHECK-NEXT: br $outer + ;; CHECK-NEXT: end + ;; CHECK-NEXT: tuple.drop 2 + ;; CHECK-NEXT: br $outer + ;; CHECK-NEXT: end + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: end ;; CHECK-NEXT: ) (func $test (block $outer diff --git a/test/lit/passes/stack-ir-non-nullable.wast b/test/lit/passes/stack-ir-non-nullable.wast index c705375be95..c3309d65a74 100644 --- a/test/lit/passes/stack-ir-non-nullable.wast +++ b/test/lit/passes/stack-ir-non-nullable.wast @@ -61,32 +61,20 @@ ;; CHECK: (func $if-no-last-get (type $1) (param $param (ref eq)) (result (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: ref.eq + ;; CHECK-NEXT: if + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: else + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $param ;; CHECK-NEXT: ) (func $if-no-last-get (param $param (ref eq)) (result (ref eq)) ;; As the original, but now there is no final get, so we can remove the set- @@ -122,35 +110,20 @@ ;; CHECK: (func $if-extra-set (type $1) (param $param (ref eq)) (result (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: ref.eq + ;; CHECK-NEXT: if + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: else + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $param ;; CHECK-NEXT: ) (func $if-extra-set (param $param (ref eq)) (result (ref eq)) ;; As the original, but now there is an extra set before the final get, so @@ -189,35 +162,24 @@ ;; CHECK: (func $if-wrong-extra-set (type $1) (param $param (ref eq)) (result (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $param - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: ref.eq + ;; CHECK-NEXT: if + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: else + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $param + ;; CHECK-NEXT: local.get $temp ;; CHECK-NEXT: ) (func $if-wrong-extra-set (param $param (ref eq)) (result (ref eq)) ;; As the last testcase, but the extra set's index is wrong, so we cannot @@ -256,35 +218,22 @@ ;; CHECK: (func $if-wrong-extra-get (type $1) (param $param (ref eq)) (result (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $param) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: ref.eq + ;; CHECK-NEXT: if + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: else + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: local.get $param ;; CHECK-NEXT: ) (func $if-wrong-extra-get (param $param (ref eq)) (result (ref eq)) ;; As the last testcase, but now it is the get that has the wrong index to @@ -323,32 +272,20 @@ ) ;; CHECK: (func $if-param (type $2) (param $param (ref eq)) (param $temp (ref eq)) (result (ref eq)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: ref.eq + ;; CHECK-NEXT: if + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: else + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $temp ;; CHECK-NEXT: ) (func $if-param (param $param (ref eq)) (param $temp (ref eq)) (result (ref eq)) ;; As the original testcase, but now $temp is a param. Validation is no @@ -383,32 +320,20 @@ ;; CHECK: (func $if-nullable (type $3) (param $param (ref eq)) (result eqref) ;; CHECK-NEXT: (local $temp eqref) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: ref.eq + ;; CHECK-NEXT: if + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: else + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $temp ;; CHECK-NEXT: ) (func $if-nullable (param $param (ref eq)) (result (ref null eq)) (local $temp (ref null eq)) ;; this changed @@ -444,45 +369,30 @@ ;; CHECK: (func $if-nondefaultable (type $1) (param $param (ref eq)) (result (ref eq)) ;; CHECK-NEXT: (local $temp (tuple i32 (ref eq))) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (tuple.make 2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (tuple.extract 2 1 - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (tuple.make 2 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (tuple.make 2 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (tuple.extract 2 1 - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: tuple.make 2 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: tuple.extract 2 1 + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: ref.eq + ;; CHECK-NEXT: if + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: i32.const 3 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: tuple.make 2 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: else + ;; CHECK-NEXT: i32.const 4 + ;; CHECK-NEXT: i32.const 5 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: tuple.make 2 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: tuple.extract 2 1 ;; CHECK-NEXT: ) (func $if-nondefaultable (param $param (ref eq)) (result (ref eq)) (local $temp (tuple i32 (ref eq))) @@ -532,45 +442,30 @@ ;; CHECK: (func $if-defaultable (type $4) (param $param eqref) (result eqref) ;; CHECK-NEXT: (local $temp (tuple i32 eqref)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (tuple.make 2 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (tuple.extract 2 1 - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (tuple.make 2 - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (tuple.make 2 - ;; CHECK-NEXT: (i32.const 4) - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 5) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (tuple.extract 2 1 - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: tuple.make 2 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: tuple.extract 2 1 + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: ref.eq + ;; CHECK-NEXT: if + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: i32.const 3 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: tuple.make 2 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: else + ;; CHECK-NEXT: i32.const 4 + ;; CHECK-NEXT: i32.const 5 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: tuple.make 2 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: tuple.extract 2 1 ;; CHECK-NEXT: ) (func $if-defaultable (param $param (ref null eq)) (result (ref null eq)) (local $temp (tuple i32 (ref null eq))) @@ -619,25 +514,16 @@ ;; CHECK: (func $if-non-ref (type $5) (param $param i32) (result i32) ;; CHECK-NEXT: (local $temp i32) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (i32.const 2) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: i32.eqz + ;; CHECK-NEXT: if + ;; CHECK-NEXT: i32.const 1 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: else + ;; CHECK-NEXT: i32.const 2 + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $temp ;; CHECK-NEXT: ) (func $if-non-ref (param $param i32) (result i32) (local $temp i32) @@ -666,37 +552,26 @@ ;; CHECK: (func $nesting (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: if + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: else + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $nesting (param $param (ref eq)) (local $temp (ref eq)) @@ -742,31 +617,20 @@ ;; CHECK: (func $nesting-left (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: if + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: else + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: end ;; CHECK-NEXT: ) (func $nesting-left (param $param (ref eq)) (local $temp (ref eq)) @@ -805,31 +669,20 @@ ;; CHECK: (func $nesting-right (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: if + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: else + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: end ;; CHECK-NEXT: ) (func $nesting-right (param $param (ref eq)) (local $temp (ref eq)) @@ -868,28 +721,16 @@ ;; CHECK: (func $nesting-both (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: if + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: else + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: end ;; CHECK-NEXT: ) (func $nesting-both (param $param (ref eq)) (local $temp (ref eq)) @@ -926,25 +767,14 @@ ;; CHECK: (func $nesting-both-less (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: if + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: else + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: end ;; CHECK-NEXT: ) (func $nesting-both-less (param $param (ref eq)) (local $temp (ref eq)) @@ -977,31 +807,16 @@ ;; CHECK: (func $nesting-both-after (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: if + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: else + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $nesting-both-after (param $param (ref eq)) (local $temp (ref eq)) @@ -1041,14 +856,8 @@ ;; CHECK: (func $nesting-irrelevant (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $nesting-irrelevant (param $param (ref eq)) (local $temp (ref eq)) @@ -1066,17 +875,12 @@ ;; CHECK: (func $nesting-relevant (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $nesting-relevant (param $param (ref eq)) (local $temp (ref eq)) @@ -1096,20 +900,10 @@ ;; CHECK: (func $nesting-after (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $nesting-after (param $param (ref eq)) (local $temp (ref eq)) @@ -1132,20 +926,10 @@ ;; CHECK: (func $nesting-reverse (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $nesting-reverse (param $param (ref eq)) (local $temp (ref eq)) @@ -1169,23 +953,16 @@ ;; CHECK: (func $nesting-covered-but-ended (type $0) (param $param (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block $block - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: drop + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: drop ;; CHECK-NEXT: ) (func $nesting-covered-but-ended (param $param (ref eq)) (local $temp (ref eq)) @@ -1214,30 +991,21 @@ ;; CHECK: (func $two-covers (type $1) (param $param (ref eq)) (result (ref eq)) ;; CHECK-NEXT: (local $temp (ref eq)) - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (ref.eq - ;; CHECK-NEXT: (local.get $temp) - ;; CHECK-NEXT: (ref.i31 - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (then - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.tee $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (else - ;; CHECK-NEXT: (local.set $temp - ;; CHECK-NEXT: (local.get $param) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $temp) + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: local.get $temp + ;; CHECK-NEXT: i32.const 0 + ;; CHECK-NEXT: ref.i31 + ;; CHECK-NEXT: ref.eq + ;; CHECK-NEXT: if + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.tee $temp + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: else + ;; CHECK-NEXT: local.get $param + ;; CHECK-NEXT: local.set $temp + ;; CHECK-NEXT: end + ;; CHECK-NEXT: local.get $temp ;; CHECK-NEXT: ) (func $two-covers (param $param (ref eq)) (result (ref eq)) (local $temp (ref eq)) diff --git a/test/lit/passes/translate-to-new-eh.wast b/test/lit/passes/translate-to-new-eh.wast index 0e9770f72de..10de158d4b6 100644 --- a/test/lit/passes/translate-to-new-eh.wast +++ b/test/lit/passes/translate-to-new-eh.wast @@ -52,14 +52,12 @@ ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $bar (type $1) - ;; STACKIR-OPT-NEXT: (nop) ;; STACKIR-OPT-NEXT: ) (func $bar) ;; CHECK: (func $baz (type $1) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $baz (type $1) - ;; STACKIR-OPT-NEXT: (nop) ;; STACKIR-OPT-NEXT: ) (func $baz) @@ -84,19 +82,19 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-none-tag-none (type $1) - ;; STACKIR-OPT-NEXT: (block $outer0 - ;; STACKIR-OPT-NEXT: (block $catch_all2 - ;; STACKIR-OPT-NEXT: (block $catch1 - ;; STACKIR-OPT-NEXT: (try_table (catch $e-empty $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (br $outer0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (call $bar) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 + ;; STACKIR-OPT-NEXT: block $catch_all2 + ;; STACKIR-OPT-NEXT: block $catch1 + ;; STACKIR-OPT-NEXT: try_table (catch $e-empty $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: call $bar + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-none-tag-none ;; try's type is none and catch's tag type is none @@ -138,26 +136,18 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-none-tag-none-with-rethrow (type $1) ;; STACKIR-OPT-NEXT: (local $0 exnref) - ;; STACKIR-OPT-NEXT: (block $outer0 - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch1 (result exnref) - ;; STACKIR-OPT-NEXT: (try_table (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 + ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: block $catch1 (result exnref) + ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-none-tag-none-with-rethrow ;; try's type is none and catch's tag type is none, and there are rethrows @@ -196,23 +186,19 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-none-tag-single (type $1) ;; STACKIR-OPT-NEXT: (local $0 i32) - ;; STACKIR-OPT-NEXT: (block $outer0 - ;; STACKIR-OPT-NEXT: (block $catch_all2 - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch1 (result i32) - ;; STACKIR-OPT-NEXT: (try_table (catch $e-i32 $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (drop - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (call $bar) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 + ;; STACKIR-OPT-NEXT: block $catch_all2 + ;; STACKIR-OPT-NEXT: block $catch1 (result i32) + ;; STACKIR-OPT-NEXT: try_table (catch $e-i32 $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: drop + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: call $bar + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-none-tag-single ;; try's type is none and catch's tag type is single @@ -275,41 +261,26 @@ ;; STACKIR-OPT-NEXT: (local $0 exnref) ;; STACKIR-OPT-NEXT: (local $1 i32) ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 exnref)) - ;; STACKIR-OPT-NEXT: (block $outer0 - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: (local.set $2 - ;; STACKIR-OPT-NEXT: (block $catch1 (type $3) (result i32 exnref) - ;; STACKIR-OPT-NEXT: (try_table (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $1 - ;; STACKIR-OPT-NEXT: (tuple.extract 2 0 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (tuple.extract 2 1 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (block - ;; STACKIR-OPT-NEXT: (drop - ;; STACKIR-OPT-NEXT: (local.get $1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 + ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: block $catch1 (type $3) (result i32 exnref) + ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: local.set $2 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 2 0 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 2 1 + ;; STACKIR-OPT-NEXT: local.set $0 + ;; STACKIR-OPT-NEXT: drop + ;; STACKIR-OPT-NEXT: local.get $0 + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-none-tag-single-with-rethrow ;; try's type is none and catch's tag type is single, and there are rethrows @@ -351,23 +322,21 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-none-tag-tuple (type $1) ;; STACKIR-OPT-NEXT: (local $0 (tuple i32 i64)) - ;; STACKIR-OPT-NEXT: (block $outer0 - ;; STACKIR-OPT-NEXT: (block $catch_all2 - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch1 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: (try_table (catch $e-i32-i64 $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (tuple.drop 2 - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (call $bar) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 + ;; STACKIR-OPT-NEXT: block $catch_all2 + ;; STACKIR-OPT-NEXT: block $catch1 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: try_table (catch $e-i32-i64 $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: local.set $0 + ;; STACKIR-OPT-NEXT: local.get $0 + ;; STACKIR-OPT-NEXT: tuple.drop 2 + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: call $bar + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-none-tag-tuple ;; try's type is none and catch's tag type is tuple @@ -435,46 +404,29 @@ ;; STACKIR-OPT-NEXT: (local $0 exnref) ;; STACKIR-OPT-NEXT: (local $1 (tuple i32 i64)) ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 i64 exnref)) - ;; STACKIR-OPT-NEXT: (block $outer0 - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: (local.set $2 - ;; STACKIR-OPT-NEXT: (block $catch1 (type $4) (result i32 i64 exnref) - ;; STACKIR-OPT-NEXT: (try_table (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $1 - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (tuple.extract 3 0 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (tuple.extract 3 1 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (tuple.extract 3 2 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (block - ;; STACKIR-OPT-NEXT: (tuple.drop 2 - ;; STACKIR-OPT-NEXT: (local.get $1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 + ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: block $catch1 (type $4) (result i32 i64 exnref) + ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: local.set $2 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 3 0 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 3 1 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: local.set $1 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 3 2 + ;; STACKIR-OPT-NEXT: local.get $1 + ;; STACKIR-OPT-NEXT: tuple.drop 2 + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-none-tag-tuple-with-rethrow ;; try's type is none and catch's tag type is tuple, and there are rethrows @@ -513,22 +465,20 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-single-tag-none (type $2) (result i32) - ;; STACKIR-OPT-NEXT: (block $outer0 (result i32) - ;; STACKIR-OPT-NEXT: (block $catch_all2 - ;; STACKIR-OPT-NEXT: (block $catch1 - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch $e-empty $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (i32.const 1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (i32.const 2) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 (result i32) + ;; STACKIR-OPT-NEXT: block $catch_all2 + ;; STACKIR-OPT-NEXT: block $catch1 + ;; STACKIR-OPT-NEXT: try_table (result i32) (catch $e-empty $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: i32.const 1 + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: i32.const 2 + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-single-tag-none (result i32) ;; try's type is single and catch's tag type is none @@ -573,28 +523,19 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-single-tag-none-with-rethrow (type $2) (result i32) ;; STACKIR-OPT-NEXT: (local $0 exnref) - ;; STACKIR-OPT-NEXT: (block $outer0 (result i32) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch1 (result exnref) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 (result i32) + ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: block $catch1 (result exnref) + ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-single-tag-none-with-rethrow (result i32) ;; try's type is single and catch's tag type is none, and there are rethrows @@ -635,24 +576,19 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-single-tag-single (type $2) (result i32) ;; STACKIR-OPT-NEXT: (local $0 i32) - ;; STACKIR-OPT-NEXT: (block $outer0 (result i32) - ;; STACKIR-OPT-NEXT: (block $catch_all2 - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch1 (result i32) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch $e-i32 $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (i32.const 2) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 (result i32) + ;; STACKIR-OPT-NEXT: block $catch_all2 + ;; STACKIR-OPT-NEXT: block $catch1 (result i32) + ;; STACKIR-OPT-NEXT: try_table (result i32) (catch $e-i32 $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: i32.const 2 + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-single-tag-single (result i32) ;; try's type is single and catch's tag type is single @@ -718,45 +654,27 @@ ;; STACKIR-OPT-NEXT: (local $0 exnref) ;; STACKIR-OPT-NEXT: (local $1 i32) ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 exnref)) - ;; STACKIR-OPT-NEXT: (block $outer0 (result i32) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: (local.set $2 - ;; STACKIR-OPT-NEXT: (block $catch1 (type $3) (result i32 exnref) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $1 - ;; STACKIR-OPT-NEXT: (tuple.extract 2 0 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (tuple.extract 2 1 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (block (result i32) - ;; STACKIR-OPT-NEXT: (drop - ;; STACKIR-OPT-NEXT: (local.get $1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 (result i32) + ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: block $catch1 (type $3) (result i32 exnref) + ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: local.set $2 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 2 0 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 2 1 + ;; STACKIR-OPT-NEXT: local.set $0 + ;; STACKIR-OPT-NEXT: drop + ;; STACKIR-OPT-NEXT: local.get $0 + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-single-tag-single-with-rethrow (result i32) ;; try's type is single and catch's tag type is single, and there are @@ -806,29 +724,23 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-single-tag-tuple (type $2) (result i32) ;; STACKIR-OPT-NEXT: (local $0 (tuple i32 i64)) - ;; STACKIR-OPT-NEXT: (block $outer0 (result i32) - ;; STACKIR-OPT-NEXT: (block $catch_all2 - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch1 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch $e-i32-i64 $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (block (result i32) - ;; STACKIR-OPT-NEXT: (tuple.drop 2 - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (i32.const 1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (i32.const 2) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 (result i32) + ;; STACKIR-OPT-NEXT: block $catch_all2 + ;; STACKIR-OPT-NEXT: block $catch1 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: try_table (result i32) (catch $e-i32-i64 $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: local.set $0 + ;; STACKIR-OPT-NEXT: local.get $0 + ;; STACKIR-OPT-NEXT: tuple.drop 2 + ;; STACKIR-OPT-NEXT: i32.const 1 + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: i32.const 2 + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-single-tag-tuple (result i32) ;; try's type is single and catch's tag type is tuple @@ -902,50 +814,30 @@ ;; STACKIR-OPT-NEXT: (local $0 exnref) ;; STACKIR-OPT-NEXT: (local $1 (tuple i32 i64)) ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 i64 exnref)) - ;; STACKIR-OPT-NEXT: (block $outer0 (result i32) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: (local.set $2 - ;; STACKIR-OPT-NEXT: (block $catch1 (type $4) (result i32 i64 exnref) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $1 - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (tuple.extract 3 0 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (tuple.extract 3 1 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (tuple.extract 3 2 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (block (result i32) - ;; STACKIR-OPT-NEXT: (tuple.drop 2 - ;; STACKIR-OPT-NEXT: (local.get $1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 (result i32) + ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: block $catch1 (type $4) (result i32 i64 exnref) + ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: local.set $2 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 3 0 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 3 1 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: local.set $1 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 3 2 + ;; STACKIR-OPT-NEXT: local.get $1 + ;; STACKIR-OPT-NEXT: tuple.drop 2 + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-single-tag-tuple-with-rethrow (result i32) ;; try's type is single and catch's tag type is tuple, and there are @@ -995,31 +887,26 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-tuple-tag-none (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: (block $outer0 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: (block $catch_all2 - ;; STACKIR-OPT-NEXT: (block $catch1 - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (try_table (type $0) (result i32 i64) (catch $e-empty $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: (i64.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (i32.const 1) - ;; STACKIR-OPT-NEXT: (i64.const 1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (i32.const 2) - ;; STACKIR-OPT-NEXT: (i64.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: block $catch_all2 + ;; STACKIR-OPT-NEXT: block $catch1 + ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch $e-empty $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: i64.const 0 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: i32.const 1 + ;; STACKIR-OPT-NEXT: i64.const 1 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: i32.const 2 + ;; STACKIR-OPT-NEXT: i64.const 0 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-tuple-tag-none (result i32 i64) ;; try's type is tuple and catch's tag type is none @@ -1076,31 +963,21 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-tuple-tag-none-with-rethrow (type $0) (result i32 i64) ;; STACKIR-OPT-NEXT: (local $0 exnref) - ;; STACKIR-OPT-NEXT: (block $outer0 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch1 (result exnref) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (try_table (type $0) (result i32 i64) (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: (i64.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: block $catch1 (result exnref) + ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch_ref $e-empty $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: i64.const 0 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-tuple-tag-none-with-rethrow (result i32 i64) ;; try's type is tuple and catch's tag type is none, and there are rethrows @@ -1153,33 +1030,25 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-tuple-tag-single (type $0) (result i32 i64) ;; STACKIR-OPT-NEXT: (local $0 i32) - ;; STACKIR-OPT-NEXT: (block $outer0 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: (block $catch_all2 - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch1 (result i32) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (try_table (type $0) (result i32 i64) (catch $e-i32 $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: (i64.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: (i64.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (i32.const 2) - ;; STACKIR-OPT-NEXT: (i64.const 2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: block $catch_all2 + ;; STACKIR-OPT-NEXT: block $catch1 (result i32) + ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch $e-i32 $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: i64.const 0 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: i64.const 0 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: i32.const 2 + ;; STACKIR-OPT-NEXT: i64.const 2 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-tuple-tag-single (result i32 i64) ;; try's type is tuple and catch's tag type is single @@ -1257,48 +1126,29 @@ ;; STACKIR-OPT-NEXT: (local $0 exnref) ;; STACKIR-OPT-NEXT: (local $1 i32) ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 exnref)) - ;; STACKIR-OPT-NEXT: (block $outer0 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: (local.set $2 - ;; STACKIR-OPT-NEXT: (block $catch1 (type $3) (result i32 exnref) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (try_table (type $0) (result i32 i64) (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: (i64.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $1 - ;; STACKIR-OPT-NEXT: (tuple.extract 2 0 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (tuple.extract 2 1 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (block (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: (drop - ;; STACKIR-OPT-NEXT: (local.get $1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: block $catch1 (type $3) (result i32 exnref) + ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch_ref $e-i32 $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: i64.const 0 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: local.set $2 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 2 0 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 2 1 + ;; STACKIR-OPT-NEXT: local.set $0 + ;; STACKIR-OPT-NEXT: drop + ;; STACKIR-OPT-NEXT: local.get $0 + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-tuple-tag-single-with-rethrow (result i32 i64) ;; try's type is tuple and catch's tag type is single, and there are @@ -1352,30 +1202,25 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-tuple-tag-tuple (type $0) (result i32 i64) ;; STACKIR-OPT-NEXT: (local $0 (tuple i32 i64)) - ;; STACKIR-OPT-NEXT: (block $outer0 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: (block $catch_all2 - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch1 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (try_table (type $0) (result i32 i64) (catch $e-i32-i64 $catch1) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: (i64.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (i32.const 2) - ;; STACKIR-OPT-NEXT: (i64.const 2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: block $catch_all2 + ;; STACKIR-OPT-NEXT: block $catch1 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch $e-i32-i64 $catch1) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: i64.const 0 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: local.set $0 + ;; STACKIR-OPT-NEXT: local.get $0 + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: i32.const 2 + ;; STACKIR-OPT-NEXT: i64.const 2 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-tuple-tag-tuple (result i32 i64) ;; try's type is tuple and catch's tag type is tuple @@ -1455,53 +1300,32 @@ ;; STACKIR-OPT-NEXT: (local $0 exnref) ;; STACKIR-OPT-NEXT: (local $1 (tuple i32 i64)) ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 i64 exnref)) - ;; STACKIR-OPT-NEXT: (block $outer0 (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch_all2 (result exnref) - ;; STACKIR-OPT-NEXT: (local.set $2 - ;; STACKIR-OPT-NEXT: (block $catch1 (type $4) (result i32 i64 exnref) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (try_table (type $0) (result i32 i64) (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: (i64.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $1 - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (tuple.extract 3 0 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (tuple.extract 3 1 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (tuple.extract 3 2 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0 - ;; STACKIR-OPT-NEXT: (block (type $0) (result i32 i64) - ;; STACKIR-OPT-NEXT: (tuple.drop 2 - ;; STACKIR-OPT-NEXT: (local.get $1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 (type $0) (result i32 i64) + ;; STACKIR-OPT-NEXT: block $catch_all2 (result exnref) + ;; STACKIR-OPT-NEXT: block $catch1 (type $4) (result i32 i64 exnref) + ;; STACKIR-OPT-NEXT: try_table (type $0) (result i32 i64) (catch_ref $e-i32-i64 $catch1) (catch_all_ref $catch_all2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: i64.const 0 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: local.set $2 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 3 0 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 3 1 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: local.set $1 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.extract 3 2 + ;; STACKIR-OPT-NEXT: local.get $1 + ;; STACKIR-OPT-NEXT: tuple.drop 2 + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-tuple-tag-tuple-with-rethrow (result i32 i64) ;; try's type is tuple and catch's tag type is tuple, and there are @@ -1535,9 +1359,9 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $catchless-delegateless-try (type $1) - ;; STACKIR-OPT-NEXT: (try_table - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: try_table + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $catchless-delegateless-try (try @@ -1629,75 +1453,43 @@ ;; STACKIR-OPT-NEXT: (local $2 (tuple i32 i64)) ;; STACKIR-OPT-NEXT: (local $3 (tuple i32 exnref)) ;; STACKIR-OPT-NEXT: (local $4 (tuple i32 i64 exnref)) - ;; STACKIR-OPT-NEXT: (block $outer0 - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch_all4 (result exnref) - ;; STACKIR-OPT-NEXT: (local.set $4 - ;; STACKIR-OPT-NEXT: (block $catch3 (type $4) (result i32 i64 exnref) - ;; STACKIR-OPT-NEXT: (local.set $3 - ;; STACKIR-OPT-NEXT: (block $catch2 (type $3) (result i32 exnref) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch1 (result exnref) - ;; STACKIR-OPT-NEXT: (try_table (catch_ref $e-empty $catch1) (catch_ref $e-i32 $catch2) (catch_ref $e-i32-i64 $catch3) (catch_all_ref $catch_all4) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $1 - ;; STACKIR-OPT-NEXT: (tuple.extract 2 0 - ;; STACKIR-OPT-NEXT: (local.get $3) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (tuple.extract 2 1 - ;; STACKIR-OPT-NEXT: (local.get $3) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (block - ;; STACKIR-OPT-NEXT: (drop - ;; STACKIR-OPT-NEXT: (local.get $1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $2 - ;; STACKIR-OPT-NEXT: (tuple.make 2 - ;; STACKIR-OPT-NEXT: (tuple.extract 3 0 - ;; STACKIR-OPT-NEXT: (local.get $4) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (tuple.extract 3 1 - ;; STACKIR-OPT-NEXT: (local.get $4) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (tuple.extract 3 2 - ;; STACKIR-OPT-NEXT: (local.get $4) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (block - ;; STACKIR-OPT-NEXT: (tuple.drop 2 - ;; STACKIR-OPT-NEXT: (local.get $2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer0 + ;; STACKIR-OPT-NEXT: block $catch_all4 (result exnref) + ;; STACKIR-OPT-NEXT: block $catch3 (type $4) (result i32 i64 exnref) + ;; STACKIR-OPT-NEXT: block $catch2 (type $3) (result i32 exnref) + ;; STACKIR-OPT-NEXT: block $catch1 (result exnref) + ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-empty $catch1) (catch_ref $e-i32 $catch2) (catch_ref $e-i32-i64 $catch3) (catch_all_ref $catch_all4) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: local.set $3 + ;; STACKIR-OPT-NEXT: local.get $3 + ;; STACKIR-OPT-NEXT: tuple.extract 2 0 + ;; STACKIR-OPT-NEXT: local.get $3 + ;; STACKIR-OPT-NEXT: tuple.extract 2 1 + ;; STACKIR-OPT-NEXT: local.set $0 + ;; STACKIR-OPT-NEXT: drop + ;; STACKIR-OPT-NEXT: local.get $0 + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: local.set $4 + ;; STACKIR-OPT-NEXT: local.get $4 + ;; STACKIR-OPT-NEXT: tuple.extract 3 0 + ;; STACKIR-OPT-NEXT: local.get $4 + ;; STACKIR-OPT-NEXT: tuple.extract 3 1 + ;; STACKIR-OPT-NEXT: tuple.make 2 + ;; STACKIR-OPT-NEXT: local.set $2 + ;; STACKIR-OPT-NEXT: local.get $4 + ;; STACKIR-OPT-NEXT: tuple.extract 3 2 + ;; STACKIR-OPT-NEXT: local.get $2 + ;; STACKIR-OPT-NEXT: tuple.drop 2 + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $multiple-catches-and-catch_all (try $l0 @@ -1760,34 +1552,28 @@ ;; STACKIR-OPT: (func $nested-catch-rethrows (type $1) ;; STACKIR-OPT-NEXT: (local $0 exnref) ;; STACKIR-OPT-NEXT: (local $1 exnref) - ;; STACKIR-OPT-NEXT: (block $outer3 - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch_all4 (result exnref) - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $catch_all4) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer3) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (block $outer0 - ;; STACKIR-OPT-NEXT: (local.set $1 - ;; STACKIR-OPT-NEXT: (block $catch2 (result exnref) - ;; STACKIR-OPT-NEXT: (block $catch1 - ;; STACKIR-OPT-NEXT: (try_table (catch $e-empty $catch1) (catch_ref $e-empty $catch2) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer3 + ;; STACKIR-OPT-NEXT: block $catch_all4 (result exnref) + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $catch_all4) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer3 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: local.set $0 + ;; STACKIR-OPT-NEXT: block $outer0 + ;; STACKIR-OPT-NEXT: block $catch2 (result exnref) + ;; STACKIR-OPT-NEXT: block $catch1 + ;; STACKIR-OPT-NEXT: try_table (catch $e-empty $catch1) (catch_ref $e-empty $catch2) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: local.get $0 + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $nested-catch-rethrows (try $l0 @@ -1839,23 +1625,22 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $delegate-target-outer-try-none (type $1) - ;; STACKIR-OPT-NEXT: (block $outer1 - ;; STACKIR-OPT-NEXT: (block $catch_all2 - ;; STACKIR-OPT-NEXT: (try_table (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $l00 (result exnref) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l00) - ;; STACKIR-OPT-NEXT: (call $bar) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (call $baz) - ;; STACKIR-OPT-NEXT: (br $outer1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (nop) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer1 + ;; STACKIR-OPT-NEXT: block $catch_all2 + ;; STACKIR-OPT-NEXT: try_table (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: block $l00 (result exnref) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) + ;; STACKIR-OPT-NEXT: call $bar + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: call $baz + ;; STACKIR-OPT-NEXT: br $outer1 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: unreachable + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $delegate-target-outer-try-none ;; An inner try-delegate targets an outer try whose type is none @@ -1897,26 +1682,25 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $multiple-delegates-target-outer-try-none (type $1) - ;; STACKIR-OPT-NEXT: (block $outer1 - ;; STACKIR-OPT-NEXT: (block $catch_all2 - ;; STACKIR-OPT-NEXT: (try_table (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $l00 (result exnref) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l00) - ;; STACKIR-OPT-NEXT: (call $bar) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l00) - ;; STACKIR-OPT-NEXT: (call $bar) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (call $baz) - ;; STACKIR-OPT-NEXT: (br $outer1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (nop) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer1 + ;; STACKIR-OPT-NEXT: block $catch_all2 + ;; STACKIR-OPT-NEXT: try_table (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: block $l00 (result exnref) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) + ;; STACKIR-OPT-NEXT: call $bar + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) + ;; STACKIR-OPT-NEXT: call $bar + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: call $baz + ;; STACKIR-OPT-NEXT: br $outer1 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: unreachable + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $multiple-delegates-target-outer-try-none ;; Multiple inner try-delegates target an outer try whose type is none @@ -1966,28 +1750,23 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $delegate-target-outer-try-concrete (type $2) (result i32) - ;; STACKIR-OPT-NEXT: (block $outer1 (result i32) - ;; STACKIR-OPT-NEXT: (block $catch_all2 - ;; STACKIR-OPT-NEXT: (br $outer1 - ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $l00 (result exnref) - ;; STACKIR-OPT-NEXT: (br $outer1 - ;; STACKIR-OPT-NEXT: (block (result i32) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch_all_ref $l00) - ;; STACKIR-OPT-NEXT: (call $bar) - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (i32.const 1) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer1 (result i32) + ;; STACKIR-OPT-NEXT: block $catch_all2 + ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: block $l00 (result exnref) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_all_ref $l00) + ;; STACKIR-OPT-NEXT: call $bar + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer1 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer1 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: i32.const 1 + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $delegate-target-outer-try-concrete (result i32) ;; An inner try-delegate targets an outer try whose type is concrete @@ -2021,16 +1800,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $deletate-target-outer-try-unreachable (type $1) - ;; STACKIR-OPT-NEXT: (try_table - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $l00 (result exnref) - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l00) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (return) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: try_table + ;; STACKIR-OPT-NEXT: block $l00 (result exnref) + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: return + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: unreachable ;; STACKIR-OPT-NEXT: ) (func $deletate-target-outer-try-unreachable ;; An inner try-delegate targets an outer try whose body type is unreachable @@ -2062,16 +1841,15 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $delegate-target-caller-none (type $1) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0) - ;; STACKIR-OPT-NEXT: (call $bar) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (call $baz) - ;; STACKIR-OPT-NEXT: (return) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: call $bar + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: call $baz + ;; STACKIR-OPT-NEXT: return + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref ;; STACKIR-OPT-NEXT: ) (func $delegate-target-caller-none ;; A try-delegate targets the caller whose type is none @@ -2101,19 +1879,18 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $multiple-delegates-target-caller-none (type $1) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0) - ;; STACKIR-OPT-NEXT: (call $bar) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0) - ;; STACKIR-OPT-NEXT: (call $bar) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (call $baz) - ;; STACKIR-OPT-NEXT: (return) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: call $bar + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: call $bar + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: call $baz + ;; STACKIR-OPT-NEXT: return + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref ;; STACKIR-OPT-NEXT: ) (func $multiple-delegates-target-caller-none ;; Multiple try-delegates target the caller whose type is none @@ -2149,19 +1926,15 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $delegate-target-caller-concrete (type $2) (result i32) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref) - ;; STACKIR-OPT-NEXT: (return - ;; STACKIR-OPT-NEXT: (block (result i32) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch_all_ref $__binaryen_delegate_caller_target0) - ;; STACKIR-OPT-NEXT: (call $bar) - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: call $bar + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: return + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref ;; STACKIR-OPT-NEXT: ) (func $delegate-target-caller-concrete (result i32) ;; A try-delegate targets the caller whose type is concrete @@ -2201,29 +1974,27 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $delegate-nested-more (type $1) - ;; STACKIR-OPT-NEXT: (block $outer3 - ;; STACKIR-OPT-NEXT: (block $catch_all4 - ;; STACKIR-OPT-NEXT: (try_table (catch_all $catch_all4) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $l00 (result exnref) - ;; STACKIR-OPT-NEXT: (block $outer1 - ;; STACKIR-OPT-NEXT: (block $catch_all2 - ;; STACKIR-OPT-NEXT: (try_table (catch_all $catch_all2) - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l00) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (nop) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer3) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (nop) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer3 + ;; STACKIR-OPT-NEXT: block $catch_all4 + ;; STACKIR-OPT-NEXT: try_table (catch_all $catch_all4) + ;; STACKIR-OPT-NEXT: block $l00 (result exnref) + ;; STACKIR-OPT-NEXT: block $outer1 + ;; STACKIR-OPT-NEXT: block $catch_all2 + ;; STACKIR-OPT-NEXT: try_table (catch_all $catch_all2) + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer1 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer3 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: unreachable + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $delegate-nested-more (try $l0 @@ -2264,23 +2035,22 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $delegate-target-outer-try-delegate (type $1) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref) - ;; STACKIR-OPT-NEXT: (block $outer2 - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $l01 (result exnref) - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l01) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (return) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) + ;; STACKIR-OPT-NEXT: block $outer2 + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: block $l01 (result exnref) + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l01) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer2 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: unreachable + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: return + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref ;; STACKIR-OPT-NEXT: ) (func $delegate-target-outer-try-delegate ;; An inner try-delegate targets an outer try-delegate that targets the @@ -2321,26 +2091,23 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $delegate-target-outer-try-delegate-concrete (type $2) (result i32) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref) - ;; STACKIR-OPT-NEXT: (return - ;; STACKIR-OPT-NEXT: (block $outer2 (result i32) - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $l01 (result exnref) - ;; STACKIR-OPT-NEXT: (br $outer2 - ;; STACKIR-OPT-NEXT: (try_table (result i32) (catch_all_ref $l01) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: (i32.const 0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) + ;; STACKIR-OPT-NEXT: block $outer2 (result i32) + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: block $l01 (result exnref) + ;; STACKIR-OPT-NEXT: try_table (result i32) (catch_all_ref $l01) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: i32.const 0 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer2 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: unreachable + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: return + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref ;; STACKIR-OPT-NEXT: ) (func $delegate-target-outer-try-delegate-concrete (result i32) ;; An inner try-delegate targets an outer try-delegate that targets the @@ -2374,18 +2141,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $throw_ref-in-resultless-block (type $2) (result i32) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $__binaryen_delegate_caller_target0 (result exnref) - ;; STACKIR-OPT-NEXT: (return - ;; STACKIR-OPT-NEXT: (block - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $__binaryen_delegate_caller_target0) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (unreachable) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $__binaryen_delegate_caller_target0 (result exnref) + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $__binaryen_delegate_caller_target0) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: unreachable + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref ;; STACKIR-OPT-NEXT: ) (func $throw_ref-in-resultless-block (result i32) ;; When the function return type is concrete, try-delegate that targets the @@ -2424,18 +2186,18 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-delegate-within-catchless-try (type $1) - ;; STACKIR-OPT-NEXT: (block $outer1 - ;; STACKIR-OPT-NEXT: (try_table - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $l00 (result exnref) - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l00) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer1 + ;; STACKIR-OPT-NEXT: try_table + ;; STACKIR-OPT-NEXT: block $l00 (result exnref) + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l00) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer1 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: unreachable + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-delegate-within-catchless-try (try $l0 @@ -2482,33 +2244,27 @@ ;; CHECK-NEXT: ) ;; STACKIR-OPT: (func $try-catch-rethrow-with-inner-delegate (type $1) ;; STACKIR-OPT-NEXT: (local $0 exnref) - ;; STACKIR-OPT-NEXT: (block $outer2 - ;; STACKIR-OPT-NEXT: (local.set $0 - ;; STACKIR-OPT-NEXT: (block $catch3 (result exnref) - ;; STACKIR-OPT-NEXT: (try_table (catch_ref $e-empty $catch3) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer2) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (block - ;; STACKIR-OPT-NEXT: (block $outer1 - ;; STACKIR-OPT-NEXT: (try_table - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (block $l10 (result exnref) - ;; STACKIR-OPT-NEXT: (try_table (catch_all_ref $l10) - ;; STACKIR-OPT-NEXT: (call $foo) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (br $outer1) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: (throw_ref - ;; STACKIR-OPT-NEXT: (local.get $0) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) - ;; STACKIR-OPT-NEXT: ) + ;; STACKIR-OPT-NEXT: block $outer2 + ;; STACKIR-OPT-NEXT: block $catch3 (result exnref) + ;; STACKIR-OPT-NEXT: try_table (catch_ref $e-empty $catch3) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer2 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: block $outer1 + ;; STACKIR-OPT-NEXT: try_table + ;; STACKIR-OPT-NEXT: block $l10 (result exnref) + ;; STACKIR-OPT-NEXT: try_table (catch_all_ref $l10) + ;; STACKIR-OPT-NEXT: call $foo + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: br $outer1 + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: unreachable + ;; STACKIR-OPT-NEXT: end + ;; STACKIR-OPT-NEXT: throw_ref + ;; STACKIR-OPT-NEXT: end ;; STACKIR-OPT-NEXT: ) (func $try-catch-rethrow-with-inner-delegate (try $l0 diff --git a/test/passes/O1_print-stack-ir.txt b/test/passes/O1_print-stack-ir.txt index d6cececfca8..0a64713d378 100644 --- a/test/passes/O1_print-stack-ir.txt +++ b/test/passes/O1_print-stack-ir.txt @@ -28,16 +28,25 @@ (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) (func $stacky-help (param $0 i32) (result i32) - i32.const 0 - call $stacky-help - i32.const 1 - call $stacky-help - local.set $0 - i32.const 2 - call $stacky-help - drop - local.get $0 - i32.eqz - i32.add + (i32.add + (call $stacky-help + (i32.const 0) + ) + (block (result i32) + (local.set $0 + (call $stacky-help + (i32.const 1) + ) + ) + (drop + (call $stacky-help + (i32.const 2) + ) + ) + (i32.eqz + (local.get $0) + ) + ) + ) ) ) diff --git a/test/passes/O2_precompute-propagate_print-stack-ir.txt b/test/passes/O2_precompute-propagate_print-stack-ir.txt index 119d1cafb71..b0789141a81 100644 --- a/test/passes/O2_precompute-propagate_print-stack-ir.txt +++ b/test/passes/O2_precompute-propagate_print-stack-ir.txt @@ -15,8 +15,10 @@ (export "func" (func $func)) (func $func (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i64) (result i64) (local $4 i32) - i64.const 2147483647 - local.set $3 - i64.const 2147483647 + (local.set $3 + (i64.const 2147483647) + ) + (nop) + (i64.const 2147483647) ) ) diff --git a/test/passes/O2_print-stack-ir.txt b/test/passes/O2_print-stack-ir.txt index d6cececfca8..cdfccc3d467 100644 --- a/test/passes/O2_print-stack-ir.txt +++ b/test/passes/O2_print-stack-ir.txt @@ -2,6 +2,23 @@ (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) (func $stacky-help (param $0 i32) (result i32) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + local.set $0 + i32.const 2 + call $stacky-help + drop + local.get $0 + i32.eqz + i32.add + ) +) +(module + (type $0 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (; has Stack IR ;) (param $0 i32) (result i32) (i32.add (call $stacky-help (i32.const 0) @@ -24,20 +41,3 @@ ) ) ) -(module - (type $0 (func (param i32) (result i32))) - (export "stacky-help" (func $stacky-help)) - (func $stacky-help (param $0 i32) (result i32) - i32.const 0 - call $stacky-help - i32.const 1 - call $stacky-help - local.set $0 - i32.const 2 - call $stacky-help - drop - local.get $0 - i32.eqz - i32.add - ) -) diff --git a/test/passes/O3_print-stack-ir.txt b/test/passes/O3_print-stack-ir.txt index 18aa4053fd9..569c49966ea 100644 --- a/test/passes/O3_print-stack-ir.txt +++ b/test/passes/O3_print-stack-ir.txt @@ -2,6 +2,21 @@ (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) (func $stacky-help (param $0 i32) (result i32) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + i32.const 2 + call $stacky-help + drop + i32.eqz + i32.add + ) +) +(module + (type $0 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (; has Stack IR ;) (param $0 i32) (result i32) (i32.add (call $stacky-help (i32.const 0) @@ -24,18 +39,3 @@ ) ) ) -(module - (type $0 (func (param i32) (result i32))) - (export "stacky-help" (func $stacky-help)) - (func $stacky-help (param $0 i32) (result i32) - i32.const 0 - call $stacky-help - i32.const 1 - call $stacky-help - i32.const 2 - call $stacky-help - drop - i32.eqz - i32.add - ) -) diff --git a/test/passes/Os_print-stack-ir_all-features_disable-gc.txt b/test/passes/Os_print-stack-ir_all-features_disable-gc.txt index 18aa4053fd9..569c49966ea 100644 --- a/test/passes/Os_print-stack-ir_all-features_disable-gc.txt +++ b/test/passes/Os_print-stack-ir_all-features_disable-gc.txt @@ -2,6 +2,21 @@ (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) (func $stacky-help (param $0 i32) (result i32) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + i32.const 2 + call $stacky-help + drop + i32.eqz + i32.add + ) +) +(module + (type $0 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (; has Stack IR ;) (param $0 i32) (result i32) (i32.add (call $stacky-help (i32.const 0) @@ -24,18 +39,3 @@ ) ) ) -(module - (type $0 (func (param i32) (result i32))) - (export "stacky-help" (func $stacky-help)) - (func $stacky-help (param $0 i32) (result i32) - i32.const 0 - call $stacky-help - i32.const 1 - call $stacky-help - i32.const 2 - call $stacky-help - drop - i32.eqz - i32.add - ) -) diff --git a/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt b/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt index 2eb5aa7da4e..c9cacca3978 100644 --- a/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt +++ b/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt @@ -1,6 +1,23 @@ (module (type $0 (func (param i64))) (func $0 (param $var$0 i64) + block $label$1 + block $label$2 + loop $label$3 + block $label$4 + unreachable + end + unreachable + end + unreachable + end + unreachable + end + ) +) +(module + (type $0 (func (param i64))) + (func $0 (; has Stack IR ;) (param $var$0 i64) (block $label$1 (br_if $label$1 (block $label$2 @@ -17,20 +34,3 @@ ) ) ) -(module - (type $0 (func (param i64))) - (func $0 (param $var$0 i64) - block $label$1 - block $label$2 - loop $label$3 - block $label$4 - unreachable - end - unreachable - end - unreachable - end - unreachable - end - ) -) From 7967bc1a38040a151722cfe93d8c20416e01b6fd Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 11:57:01 -0700 Subject: [PATCH 38/77] fix --- src/wasm-binary.h | 1 + src/wasm/wasm-binary.cpp | 56 +++++++++++++++++++++++++++------------- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 310b251c177..4ec7e335249 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1314,6 +1314,7 @@ class WasmBinaryWriter { void writeFunctionSignatures(); void writeExpression(Expression* curr); + void prepareFunctions(); void writeFunctions(); void writeStrings(); void writeGlobals(); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 86bf846c511..811366f99a7 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -69,6 +69,7 @@ void WasmBinaryWriter::write() { writeStart(); writeElementSegments(); writeDataCount(); + prepareFunctions(); writeFunctions(); writeDataSegments(); if (debugInfo || emitModuleName) { @@ -370,6 +371,42 @@ void WasmBinaryWriter::writeImports() { finishSection(start); } +void WasmBinaryWriter::prepareFunctions() { + if (!options.generateStackIR) { + return; + } + + // Generate StackIR for functions in parallel, and optimize if requested. + struct StackIRPass + : public WalkerPass> { + bool isFunctionParallel() override { return true; } + + std::unique_ptr create() override { + return std::make_unique(); + } + + void doWalkFunction(Function* func) { + StackIRGenerator stackIRGen(*getModule(), func); + stackIRGen.write(); + func->stackIR = std::make_unique(); + func->stackIR->swap(stackIRGen.getStackIR()); + + auto& options = getPassOptions(); + if (options.optimizeStackIR) { + StackIROptimizer optimizer(func, options, getModule()->features); + optimizer.run(); + } + } + }; + + PassRunner runner(wasm, options); + StackIRPass().run(&runner, wasm); + + if (options.printStackIR) { + printStackIR(std::cout, wasm); + } +} + void WasmBinaryWriter::writeFunctionSignatures() { if (importInfo->getNumDefinedFunctions() == 0) { return; @@ -403,24 +440,7 @@ void WasmBinaryWriter::writeFunctions() { size_t sizePos = writeU32LEBPlaceholder(); size_t start = o.size(); BYN_TRACE("writing" << func->name << std::endl); - - if (options.generateStackIR) { - StackIRGenerator stackIRGen(*getModule(), func); - stackIRGen.write(); - func->stackIR = std::make_unique(); - func->stackIR->swap(stackIRGen.getStackIR()); - - if (options.optimizeStackIR) { - StackIROptimizer optimizer(func, options, wasm->features); - optimizer.run(); - } - - if (options.printStackIR) { // from a wasm-opt commandline flag - printStackIR(std::cout, wasm); - } - } - - // Emit Stack IR if present, and if we can + // Emit Stack IR if present. if (func->stackIR) { BYN_TRACE("write Stack IR\n"); StackIRToBinaryWriter writer(*this, o, func, sourceMap, DWARF); From 87878b5a624373df08a80a3fe67870358bc5b027 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 12:08:59 -0700 Subject: [PATCH 39/77] fix --- src/wasm/wasm-binary.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 811366f99a7..d45ad60d2c6 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -400,7 +400,8 @@ void WasmBinaryWriter::prepareFunctions() { }; PassRunner runner(wasm, options); - StackIRPass().run(&runner, wasm); + runner.add(std::make_unique() ); + runner.run(); if (options.printStackIR) { printStackIR(std::cout, wasm); From aa3639af489aa5415fe2a7a9489325c2c5b406e4 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:05:00 -0700 Subject: [PATCH 40/77] test --- test/passes/O1_print-stack-ir.txt | 31 ++++++----------- ...O2_precompute-propagate_print-stack-ir.txt | 8 ++--- test/passes/O2_print-stack-ir.txt | 34 +++++++++---------- test/passes/O3_print-stack-ir.txt | 30 ++++++++-------- ...print-stack-ir_all-features_disable-gc.txt | 30 ++++++++-------- ...d-brs_generate-stack-ir_print-stack-ir.txt | 34 +++++++++---------- 6 files changed, 78 insertions(+), 89 deletions(-) diff --git a/test/passes/O1_print-stack-ir.txt b/test/passes/O1_print-stack-ir.txt index 0a64713d378..d6cececfca8 100644 --- a/test/passes/O1_print-stack-ir.txt +++ b/test/passes/O1_print-stack-ir.txt @@ -28,25 +28,16 @@ (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) (func $stacky-help (param $0 i32) (result i32) - (i32.add - (call $stacky-help - (i32.const 0) - ) - (block (result i32) - (local.set $0 - (call $stacky-help - (i32.const 1) - ) - ) - (drop - (call $stacky-help - (i32.const 2) - ) - ) - (i32.eqz - (local.get $0) - ) - ) - ) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + local.set $0 + i32.const 2 + call $stacky-help + drop + local.get $0 + i32.eqz + i32.add ) ) diff --git a/test/passes/O2_precompute-propagate_print-stack-ir.txt b/test/passes/O2_precompute-propagate_print-stack-ir.txt index b0789141a81..119d1cafb71 100644 --- a/test/passes/O2_precompute-propagate_print-stack-ir.txt +++ b/test/passes/O2_precompute-propagate_print-stack-ir.txt @@ -15,10 +15,8 @@ (export "func" (func $func)) (func $func (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i64) (result i64) (local $4 i32) - (local.set $3 - (i64.const 2147483647) - ) - (nop) - (i64.const 2147483647) + i64.const 2147483647 + local.set $3 + i64.const 2147483647 ) ) diff --git a/test/passes/O2_print-stack-ir.txt b/test/passes/O2_print-stack-ir.txt index cdfccc3d467..d6cececfca8 100644 --- a/test/passes/O2_print-stack-ir.txt +++ b/test/passes/O2_print-stack-ir.txt @@ -2,23 +2,6 @@ (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) (func $stacky-help (param $0 i32) (result i32) - i32.const 0 - call $stacky-help - i32.const 1 - call $stacky-help - local.set $0 - i32.const 2 - call $stacky-help - drop - local.get $0 - i32.eqz - i32.add - ) -) -(module - (type $0 (func (param i32) (result i32))) - (export "stacky-help" (func $stacky-help)) - (func $stacky-help (; has Stack IR ;) (param $0 i32) (result i32) (i32.add (call $stacky-help (i32.const 0) @@ -41,3 +24,20 @@ ) ) ) +(module + (type $0 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (param $0 i32) (result i32) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + local.set $0 + i32.const 2 + call $stacky-help + drop + local.get $0 + i32.eqz + i32.add + ) +) diff --git a/test/passes/O3_print-stack-ir.txt b/test/passes/O3_print-stack-ir.txt index 569c49966ea..18aa4053fd9 100644 --- a/test/passes/O3_print-stack-ir.txt +++ b/test/passes/O3_print-stack-ir.txt @@ -2,21 +2,6 @@ (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) (func $stacky-help (param $0 i32) (result i32) - i32.const 0 - call $stacky-help - i32.const 1 - call $stacky-help - i32.const 2 - call $stacky-help - drop - i32.eqz - i32.add - ) -) -(module - (type $0 (func (param i32) (result i32))) - (export "stacky-help" (func $stacky-help)) - (func $stacky-help (; has Stack IR ;) (param $0 i32) (result i32) (i32.add (call $stacky-help (i32.const 0) @@ -39,3 +24,18 @@ ) ) ) +(module + (type $0 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (param $0 i32) (result i32) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + i32.const 2 + call $stacky-help + drop + i32.eqz + i32.add + ) +) diff --git a/test/passes/Os_print-stack-ir_all-features_disable-gc.txt b/test/passes/Os_print-stack-ir_all-features_disable-gc.txt index 569c49966ea..18aa4053fd9 100644 --- a/test/passes/Os_print-stack-ir_all-features_disable-gc.txt +++ b/test/passes/Os_print-stack-ir_all-features_disable-gc.txt @@ -2,21 +2,6 @@ (type $0 (func (param i32) (result i32))) (export "stacky-help" (func $stacky-help)) (func $stacky-help (param $0 i32) (result i32) - i32.const 0 - call $stacky-help - i32.const 1 - call $stacky-help - i32.const 2 - call $stacky-help - drop - i32.eqz - i32.add - ) -) -(module - (type $0 (func (param i32) (result i32))) - (export "stacky-help" (func $stacky-help)) - (func $stacky-help (; has Stack IR ;) (param $0 i32) (result i32) (i32.add (call $stacky-help (i32.const 0) @@ -39,3 +24,18 @@ ) ) ) +(module + (type $0 (func (param i32) (result i32))) + (export "stacky-help" (func $stacky-help)) + (func $stacky-help (param $0 i32) (result i32) + i32.const 0 + call $stacky-help + i32.const 1 + call $stacky-help + i32.const 2 + call $stacky-help + drop + i32.eqz + i32.add + ) +) diff --git a/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt b/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt index c9cacca3978..2eb5aa7da4e 100644 --- a/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt +++ b/test/passes/remove-unused-brs_generate-stack-ir_print-stack-ir.txt @@ -1,23 +1,6 @@ (module (type $0 (func (param i64))) (func $0 (param $var$0 i64) - block $label$1 - block $label$2 - loop $label$3 - block $label$4 - unreachable - end - unreachable - end - unreachable - end - unreachable - end - ) -) -(module - (type $0 (func (param i64))) - (func $0 (; has Stack IR ;) (param $var$0 i64) (block $label$1 (br_if $label$1 (block $label$2 @@ -34,3 +17,20 @@ ) ) ) +(module + (type $0 (func (param i64))) + (func $0 (param $var$0 i64) + block $label$1 + block $label$2 + loop $label$3 + block $label$4 + unreachable + end + unreachable + end + unreachable + end + unreachable + end + ) +) From 9a1558dc641be27cbf0ee5c58e8d03108b1529a7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:05:14 -0700 Subject: [PATCH 41/77] format --- src/tools/tool-options.h | 18 ++++++++++++------ src/wasm-binary.h | 4 +++- src/wasm-io.h | 4 +++- src/wasm/wasm-binary.cpp | 5 ++--- src/wasm/wasm-stack-opts.cpp | 20 ++++++++++++++------ 5 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h index fd98e50491c..233e6130d8a 100644 --- a/src/tools/tool-options.h +++ b/src/tools/tool-options.h @@ -157,20 +157,27 @@ struct ToolOptions : public Options { "generate StackIR during writing", ToolOptionsCategory, Options::Arguments::Zero, - [&](Options* o, const std::string& arguments) { passOptions.generateStackIR = true; }) + [&](Options* o, const std::string& arguments) { + passOptions.generateStackIR = true; + }) .add("--optimize-stack-ir", "", "optimize StackIR during writing", ToolOptionsCategory, Options::Arguments::Zero, - [&](Options* o, const std::string& arguments) { passOptions.generateStackIR = true; passOptions.optimizeStackIR = true; }) + [&](Options* o, const std::string& arguments) { + passOptions.generateStackIR = true; + passOptions.optimizeStackIR = true; + }) .add("--print-stack-ir", "", "print StackIR during writing", ToolOptionsCategory, Options::Arguments::Zero, - [&](Options* o, const std::string& arguments) { passOptions.generateStackIR = true; passOptions.printStackIR = true; }) - ; + [&](Options* o, const std::string& arguments) { + passOptions.generateStackIR = true; + passOptions.printStackIR = true; + }); } ToolOptions& addFeature(FeatureSet::Feature feature, @@ -202,8 +209,7 @@ struct ToolOptions : public Options { module.features.enable(enabledFeatures); module.features.disable(disabledFeatures); - if (passOptions.optimizeLevel >= 2 || - passOptions.shrinkLevel >= 1) { + if (passOptions.optimizeLevel >= 2 || passOptions.shrinkLevel >= 1) { passOptions.generateStackIR = true; passOptions.optimizeStackIR = true; } diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 4ec7e335249..759678bdf0b 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1270,7 +1270,9 @@ class WasmBinaryWriter { }; public: - WasmBinaryWriter(Module* input, BufferWithRandomAccess& o, const PassOptions& options) + WasmBinaryWriter(Module* input, + BufferWithRandomAccess& o, + const PassOptions& options) : wasm(input), o(o), options(options), indexes(*input) { prepare(); } diff --git a/src/wasm-io.h b/src/wasm-io.h index d8040d8c460..e5cad9a23ff 100644 --- a/src/wasm-io.h +++ b/src/wasm-io.h @@ -100,7 +100,9 @@ class ModuleWriter : public ModuleIOBase { public: // Writing defaults to not storing the names section. Storing it is a user- // observable fact that must be opted into. - ModuleWriter(const PassOptions& options) : options(options) { setDebugInfo(false); } + ModuleWriter(const PassOptions& options) : options(options) { + setDebugInfo(false); + } void setBinary(bool binary_) { binary = binary_; } void setSymbolMap(std::string symbolMap_) { symbolMap = symbolMap_; } diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index d45ad60d2c6..eca26a6388a 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -377,8 +377,7 @@ void WasmBinaryWriter::prepareFunctions() { } // Generate StackIR for functions in parallel, and optimize if requested. - struct StackIRPass - : public WalkerPass> { + struct StackIRPass : public WalkerPass> { bool isFunctionParallel() override { return true; } std::unique_ptr create() override { @@ -400,7 +399,7 @@ void WasmBinaryWriter::prepareFunctions() { }; PassRunner runner(wasm, options); - runner.add(std::make_unique() ); + runner.add(std::make_unique()); runner.run(); if (options.printStackIR) { diff --git a/src/wasm/wasm-stack-opts.cpp b/src/wasm/wasm-stack-opts.cpp index 9e4c10cf56e..f95d1cd45ee 100644 --- a/src/wasm/wasm-stack-opts.cpp +++ b/src/wasm/wasm-stack-opts.cpp @@ -27,8 +27,8 @@ namespace wasm { StackIROptimizer::StackIROptimizer(Function* func, - const PassOptions& passOptions, - FeatureSet features) + const PassOptions& passOptions, + FeatureSet features) : func(func), passOptions(passOptions), insts(*func->stackIR.get()), features(features) { assert(func->stackIR); // TODO move out of func @@ -261,7 +261,9 @@ bool StackIROptimizer::isControlFlowBarrier(StackInst* inst) { case StackInst::TryTableEnd: { return true; } - default: { return false; } + default: { + return false; + } } } @@ -275,7 +277,9 @@ bool StackIROptimizer::isControlFlowBegin(StackInst* inst) { case StackInst::TryTableBegin: { return true; } - default: { return false; } + default: { + return false; + } } } @@ -290,11 +294,15 @@ bool StackIROptimizer::isControlFlowEnd(StackInst* inst) { case StackInst::TryTableEnd: { return true; } - default: { return false; } + default: { + return false; + } } } -bool StackIROptimizer::isControlFlow(StackInst* inst) { return inst->op != StackInst::Basic; } +bool StackIROptimizer::isControlFlow(StackInst* inst) { + return inst->op != StackInst::Basic; +} // Remove the instruction at index i. If the instruction // is control flow, and so has been expanded to multiple From 61b8f767334c8a0dc88628281f69f6997b4a02c1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:08:31 -0700 Subject: [PATCH 42/77] fix --- CHANGELOG.md | 5 +++++ src/passes/Print.cpp | 3 --- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a44aedcefe0..d6cd64b33af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,11 @@ full changeset diff at the end of each section. Current Trunk ------------- + - StackIR is now handled entirely during binary writing. This is mostly not + noticeable, except that: + - Whether to generate, optimize, and print StackIR is now noted as part of + the PassOptions. As a result `BinaryenModulePrintStackIR` and similar APIs + do not receive an `optimize` flag, as they read the options. - The new, standards-compliant text parser is now the default. `wasm-opt` has a `--deprecated-wat-parser` flag that will switch back to using the old text parser, but that option will go away soon. diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 08970a35260..381ebbef4eb 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -2978,9 +2978,6 @@ void PrintSExpression::visitDefinedFunction(Function* curr) { o << " (type "; printHeapType(curr->type) << ')'; } - if (!stackIR && curr->stackIR && !minify) { - o << " (; has Stack IR ;)"; - } if (curr->getParams().size() > 0) { Index i = 0; for (const auto& param : curr->getParams()) { From f23068a41dd4a63854634cc1e65cb72277be7970 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:16:10 -0700 Subject: [PATCH 43/77] fix --- CHANGELOG.md | 5 +++++ src/tools/optimization-options.h | 8 ++++++++ src/tools/tool-options.h | 7 +------ src/tools/wasm-opt.cpp | 7 ------- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6cd64b33af..e9844e79089 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,11 @@ Current Trunk - Whether to generate, optimize, and print StackIR is now noted as part of the PassOptions. As a result `BinaryenModulePrintStackIR` and similar APIs do not receive an `optimize` flag, as they read the options. + - Text output no longer notes `(; has Stack IR ;)` (as Stack IR only exists + during binary writing). + - `--print-stack-ir` is now a flag, not a pass, which means the order of + operations may seem different, as it applies during binary writing (or, if + no binary is written, `wasm-opt` does it at the very end). - The new, standards-compliant text parser is now the default. `wasm-opt` has a `--deprecated-wat-parser` flag that will switch back to using the old text parser, but that option will go away soon. diff --git a/src/tools/optimization-options.h b/src/tools/optimization-options.h index 0a47d9f709e..1a0d1bdc9bb 100644 --- a/src/tools/optimization-options.h +++ b/src/tools/optimization-options.h @@ -56,9 +56,17 @@ struct OptimizationOptions : public ToolOptions { // level, so that the last of -O3 -Os will override the previous default, but // also we note the current opt level for when we run the pass, so that the // sequence -O3 -Os will run -O3 and then -Os, and not -Os twice. + // + // This also applies the consequences of the current optimize and shrink + // levels. void addDefaultOptPasses() { passes.push_back(PassInfo{ DEFAULT_OPT_PASSES, passOptions.optimizeLevel, passOptions.shrinkLevel}); + + if (passOptions.optimizeLevel >= 2 || passOptions.shrinkLevel >= 1) { + passOptions.generateStackIR = true; + passOptions.optimizeStackIR = true; + } } constexpr static const char* OptimizationOptionsCategory = diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h index 233e6130d8a..7f4ff3d58a3 100644 --- a/src/tools/tool-options.h +++ b/src/tools/tool-options.h @@ -205,14 +205,9 @@ struct ToolOptions : public Options { return *this; } - void applyFeatures(Module& module) { // TODO rename? + void applyFeatures(Module& module) { module.features.enable(enabledFeatures); module.features.disable(disabledFeatures); - - if (passOptions.optimizeLevel >= 2 || passOptions.shrinkLevel >= 1) { - passOptions.generateStackIR = true; - passOptions.optimizeStackIR = true; - } } private: diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index 447927c6e17..ae12ee22bdd 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -178,13 +178,6 @@ int main(int argc, const char* argv[]) { WasmOptOption, Options::Arguments::Zero, [&](Options* o, const std::string& arguments) { fuzzOOB = false; }) - .add("--no-fuzz-oob", - "", - "don't emit out-of-bounds loads/stores/indirect calls when fuzzing", - WasmOptOption, - Options::Arguments::Zero, - [&](Options* o, const std::string& arguments) { fuzzOOB = false; }) - .add("--emit-spec-wrapper", "-esw", "Emit a wasm spec interpreter wrapper file that can run the wasm with " From 8782e4830a9bfaeba597eaf4e577e5c7cbf2a28e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:17:09 -0700 Subject: [PATCH 44/77] fix --- src/pass.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pass.h b/src/pass.h index 2021b917395..1d9df419683 100644 --- a/src/pass.h +++ b/src/pass.h @@ -219,9 +219,13 @@ struct PassOptions { bool closedWorld = false; // Whether to try to preserve debug info through, which are special calls. bool debugInfo = false; - // TODO comment + // Whether to generate StackIR during binary writing. bool generateStackIR = false; + // Whether to optimize StackIR during binary writing. How we optimize depends + // on other optimization flags like optimizeLevel. bool optimizeStackIR = false; + // Whether to print StackIR during binary writing. This is mainly useful for + // debugging. bool printStackIR = false; // Whether we are targeting JS. In that case we want to avoid emitting things // in the optimizer that do not translate well to JS, or that could cause us From c10d2d88dee0820eef08a1bdceca74b6ed58761b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:24:09 -0700 Subject: [PATCH 45/77] fix --- test/lit/help/wasm-opt.test | 4 ---- test/passes/converge_O3_metrics.bin.txt | 24 ++++++++++++------------ 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test index 4578e470e0a..f6497618e65 100644 --- a/test/lit/help/wasm-opt.test +++ b/test/lit/help/wasm-opt.test @@ -53,10 +53,6 @@ ;; CHECK-NEXT: loads/stores/indirect calls when ;; CHECK-NEXT: fuzzing ;; CHECK-NEXT: -;; CHECK-NEXT: --no-fuzz-oob don't emit out-of-bounds -;; CHECK-NEXT: loads/stores/indirect calls when -;; CHECK-NEXT: fuzzing -;; CHECK-NEXT: ;; CHECK-NEXT: --emit-spec-wrapper,-esw Emit a wasm spec interpreter ;; CHECK-NEXT: wrapper file that can run the ;; CHECK-NEXT: wasm with some test values, diff --git a/test/passes/converge_O3_metrics.bin.txt b/test/passes/converge_O3_metrics.bin.txt index 7b077ceb415..312e67fe794 100644 --- a/test/passes/converge_O3_metrics.bin.txt +++ b/test/passes/converge_O3_metrics.bin.txt @@ -277,13 +277,13 @@ total (elem $0 (i32.const 0) $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $___stdout_write $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE6xsputnEPKci $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE8overflowEi) (export "_main" (func $_main)) (export "_malloc" (func $_malloc)) - (func $b0 (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (result i32) + (func $b0 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (result i32) (i32.const 0) ) - (func $_malloc (; has Stack IR ;) (param $0 i32) (result i32) + (func $_malloc (param $0 i32) (result i32) (i32.const 0) ) - (func $_main (; has Stack IR ;) (result i32) + (func $_main (result i32) (local $0 i32) (local $1 i32) (local.set $0 @@ -388,7 +388,7 @@ total ) (i32.const 0) ) - (func $___stdout_write (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $___stdout_write (param $0 i32) (param $1 i32) (param $2 i32) (result i32) (i32.store (i32.const 8) (local.get $1) @@ -413,7 +413,7 @@ total ) (i32.const 1) ) - (func $__ZNSt3__211__stdoutbufIcE8overflowEi (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) + (func $__ZNSt3__211__stdoutbufIcE8overflowEi (param $0 i32) (param $1 i32) (result i32) (i32.store8 (i32.const 0) (local.get $1) @@ -438,7 +438,7 @@ total ) (i32.const 0) ) - (func $__ZNSt3__211__stdoutbufIcE6xsputnEPKci (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $__ZNSt3__211__stdoutbufIcE6xsputnEPKci (param $0 i32) (param $1 i32) (param $2 i32) (result i32) (drop (call_indirect (type $0) (i32.const 0) @@ -503,13 +503,13 @@ total (elem $0 (i32.const 0) $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $___stdout_write $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE6xsputnEPKci $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $b0 $__ZNSt3__211__stdoutbufIcE8overflowEi) (export "_main" (func $_main)) (export "_malloc" (func $_malloc)) - (func $b0 (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (result i32) + (func $b0 (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (param $4 i32) (param $5 i32) (param $6 i32) (result i32) (i32.const 0) ) - (func $_malloc (; has Stack IR ;) (param $0 i32) (result i32) + (func $_malloc (param $0 i32) (result i32) (i32.const 0) ) - (func $_main (; has Stack IR ;) (result i32) + (func $_main (result i32) (local $0 i32) (local $1 i32) (local.set $0 @@ -614,7 +614,7 @@ total ) (i32.const 0) ) - (func $___stdout_write (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $___stdout_write (param $0 i32) (param $1 i32) (param $2 i32) (result i32) (i32.store (i32.const 8) (local.get $1) @@ -639,7 +639,7 @@ total ) (i32.const 1) ) - (func $__ZNSt3__211__stdoutbufIcE8overflowEi (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) + (func $__ZNSt3__211__stdoutbufIcE8overflowEi (param $0 i32) (param $1 i32) (result i32) (i32.store8 (i32.const 0) (local.get $1) @@ -664,7 +664,7 @@ total ) (i32.const 0) ) - (func $__ZNSt3__211__stdoutbufIcE6xsputnEPKci (; has Stack IR ;) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) + (func $__ZNSt3__211__stdoutbufIcE6xsputnEPKci (param $0 i32) (param $1 i32) (param $2 i32) (result i32) (drop (call_indirect (type $0) (i32.const 0) From 60b76db88d92839c9f1a195178446d7420728a82 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:27:37 -0700 Subject: [PATCH 46/77] fix --- test/binaryen.js/hello-world.js.txt | 2 +- test/binaryen.js/low-memory-unused.js.txt | 4 ++-- test/binaryen.js/optimize-levels.js.txt | 4 ++-- test/binaryen.js/sieve.js.txt | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/binaryen.js/hello-world.js.txt b/test/binaryen.js/hello-world.js.txt index 3f9296adfcc..70c94764a53 100644 --- a/test/binaryen.js/hello-world.js.txt +++ b/test/binaryen.js/hello-world.js.txt @@ -16,7 +16,7 @@ optimized: (module (type $0 (func (param i32 i32) (result i32))) (export "adder" (func $adder)) - (func $adder (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32) + (func $adder (param $0 i32) (param $1 i32) (result i32) (i32.add (local.get $0) (local.get $1) diff --git a/test/binaryen.js/low-memory-unused.js.txt b/test/binaryen.js/low-memory-unused.js.txt index 99c68225904..d9b10a3f629 100644 --- a/test/binaryen.js/low-memory-unused.js.txt +++ b/test/binaryen.js/low-memory-unused.js.txt @@ -32,7 +32,7 @@ (type $0 (func (param i32) (result i32))) (memory $0 1) (export "test" (func $test)) - (func $test (; has Stack IR ;) (param $0 i32) (result i32) + (func $test (param $0 i32) (result i32) (i32.load (i32.add (local.get $0) @@ -48,7 +48,7 @@ (type $0 (func (param i32) (result i32))) (memory $0 1) (export "test" (func $test)) - (func $test (; has Stack IR ;) (param $0 i32) (result i32) + (func $test (param $0 i32) (result i32) (i32.load offset=128 (local.get $0) ) diff --git a/test/binaryen.js/optimize-levels.js.txt b/test/binaryen.js/optimize-levels.js.txt index ed928fbef15..4e2902079b3 100644 --- a/test/binaryen.js/optimize-levels.js.txt +++ b/test/binaryen.js/optimize-levels.js.txt @@ -38,7 +38,7 @@ shrinkLevel=1 (module (type $i (func (param i32) (result i32))) (export "test" (func $test)) - (func $test (; has Stack IR ;) (param $0 i32) (result i32) + (func $test (param $0 i32) (result i32) (local.get $0) ) ) @@ -60,7 +60,7 @@ shrinkLevel=1 (module (type $i (func (param i32) (result i32))) (export "test" (func $test)) - (func $test (; has Stack IR ;) (param $0 i32) (result i32) + (func $test (param $0 i32) (result i32) (local.get $0) ) ) diff --git a/test/binaryen.js/sieve.js.txt b/test/binaryen.js/sieve.js.txt index 46e5d3b398c..e04b0bfe175 100644 --- a/test/binaryen.js/sieve.js.txt +++ b/test/binaryen.js/sieve.js.txt @@ -62,7 +62,7 @@ optimized: (type $0 (func (param i32) (result i32))) (memory $0 1 100) (export "sieve" (func $sieve)) - (func $sieve (; has Stack IR ;) (param $0 i32) (result i32) + (func $sieve (param $0 i32) (result i32) (local $1 i32) (if (i32.lt_u From 7295265f9b42e02a6912f420cf1a5315ae6c57a9 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:34:46 -0700 Subject: [PATCH 47/77] text --- CHANGELOG.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9844e79089..57ea4f772ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,14 +17,15 @@ Current Trunk - StackIR is now handled entirely during binary writing. This is mostly not noticeable, except that: - - Whether to generate, optimize, and print StackIR is now noted as part of - the PassOptions. As a result `BinaryenModulePrintStackIR` and similar APIs - do not receive an `optimize` flag, as they read the options. - Text output no longer notes `(; has Stack IR ;)` (as Stack IR only exists during binary writing). - `--print-stack-ir` is now a flag, not a pass, which means the order of operations may seem different, as it applies during binary writing (or, if - no binary is written, `wasm-opt` does it at the very end). + no binary is written, `wasm-opt` prints StackIR at the very end). + - Whether to generate, optimize, and print StackIR is now noted as part of + the PassOptions. As a result `BinaryenModulePrintStackIR` and similar APIs + do not receive an `optimize` flag, as they read the PassOption + `optimizeStackIR` instead. - The new, standards-compliant text parser is now the default. `wasm-opt` has a `--deprecated-wat-parser` flag that will switch back to using the old text parser, but that option will go away soon. From 188cea991e8ac8a37017a86e8ad4b073fae7b083 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:38:02 -0700 Subject: [PATCH 48/77] fix --- CHANGELOG.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57ea4f772ee..7d997e70255 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,9 +19,11 @@ Current Trunk noticeable, except that: - Text output no longer notes `(; has Stack IR ;)` (as Stack IR only exists during binary writing). - - `--print-stack-ir` is now a flag, not a pass, which means the order of - operations may seem different, as it applies during binary writing (or, if - no binary is written, `wasm-opt` prints StackIR at the very end). + - `--generate-stack-ir`, `--optimize-stack-ir`, and `--print-stack-ir` are + now flags and not passes. That means the order of operations may seem + different, as they apply during binary writing (or, if no binary is written + but we were still asked to print StackIR, `wasm-opt` does it at the very + end). - Whether to generate, optimize, and print StackIR is now noted as part of the PassOptions. As a result `BinaryenModulePrintStackIR` and similar APIs do not receive an `optimize` flag, as they read the PassOption From 6693a71b2cb8d8b3c0f0a9e6813eaff2eab8a5d8 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:39:18 -0700 Subject: [PATCH 49/77] fix --- src/pass.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pass.h b/src/pass.h index 1d9df419683..3fa98b6ca2c 100644 --- a/src/pass.h +++ b/src/pass.h @@ -219,10 +219,12 @@ struct PassOptions { bool closedWorld = false; // Whether to try to preserve debug info through, which are special calls. bool debugInfo = false; - // Whether to generate StackIR during binary writing. + // Whether to generate StackIR during binary writing. This is on by default + // in -O2 and above. bool generateStackIR = false; // Whether to optimize StackIR during binary writing. How we optimize depends - // on other optimization flags like optimizeLevel. + // on other optimization flags like optimizeLevel. This is on by default in + // -O2 and above. bool optimizeStackIR = false; // Whether to print StackIR during binary writing. This is mainly useful for // debugging. From e40b10054e61cdb515f8589d8a1bb5fac6b2c87f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:40:15 -0700 Subject: [PATCH 50/77] fix --- src/tools/tool-options.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h index 7f4ff3d58a3..4528c6ab8d3 100644 --- a/src/tools/tool-options.h +++ b/src/tools/tool-options.h @@ -166,6 +166,7 @@ struct ToolOptions : public Options { ToolOptionsCategory, Options::Arguments::Zero, [&](Options* o, const std::string& arguments) { + // Also generate StackIR, to have something to optimize. passOptions.generateStackIR = true; passOptions.optimizeStackIR = true; }) @@ -175,6 +176,7 @@ struct ToolOptions : public Options { ToolOptionsCategory, Options::Arguments::Zero, [&](Options* o, const std::string& arguments) { + // Also generate StackIR, to have something to print. passOptions.generateStackIR = true; passOptions.printStackIR = true; }); From e6cac134e971f0987c0e3b0d358dabcbd8a7ffd7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:40:27 -0700 Subject: [PATCH 51/77] fix --- src/tools/tool-options.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h index 4528c6ab8d3..75ac14a442c 100644 --- a/src/tools/tool-options.h +++ b/src/tools/tool-options.h @@ -207,7 +207,7 @@ struct ToolOptions : public Options { return *this; } - void applyFeatures(Module& module) { + void applyFeatures(Module& module) const { module.features.enable(enabledFeatures); module.features.disable(disabledFeatures); } From fc087087b217d4cf58f108ba3b9e4c59607547e7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:41:33 -0700 Subject: [PATCH 52/77] fix --- src/tools/wasm-opt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index ae12ee22bdd..42945b57fbf 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -421,7 +421,7 @@ int main(int argc, const char* argv[]) { if (options.passOptions.printStackIR) { // The user asked to print StackIR without setting an output file, so we // are not emitting a binary, but we do want to go through the binary - // writing process just to get StackIR to emit here. We can do that by + // writing process just to get StackIR to be printed. We can do that by // computing the binary size. computeBinarySize(); return 0; From d8256960888f3957b4629a6e96d485d67d484b69 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:42:55 -0700 Subject: [PATCH 53/77] fix --- src/tools/wasm-opt.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index 42945b57fbf..ada7889dd2e 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -424,7 +424,6 @@ int main(int argc, const char* argv[]) { // writing process just to get StackIR to be printed. We can do that by // computing the binary size. computeBinarySize(); - return 0; } if (!options.quiet) { std::cerr << "warning: no output file specified, not emitting output\n"; From be6a9dd3ab4e1a64fa0a708d148090897d9d6dc1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 13:50:43 -0700 Subject: [PATCH 54/77] fix --- src/tools/wasm-split/wasm-split.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/wasm-split/wasm-split.cpp b/src/tools/wasm-split/wasm-split.cpp index 3436f5bdcb6..d7dc19d677a 100644 --- a/src/tools/wasm-split/wasm-split.cpp +++ b/src/tools/wasm-split/wasm-split.cpp @@ -37,7 +37,7 @@ using namespace wasm; namespace { -void parseInput(Module& wasm, WasmSplitOptions& options) { +void parseInput(Module& wasm, const WasmSplitOptions& options) { options.applyFeatures(wasm); ModuleReader reader; reader.setProfile(options.profile); @@ -100,7 +100,7 @@ void writeModule(Module& wasm, writer.write(wasm, filename); } -void instrumentModule(WasmSplitOptions& options) { +void instrumentModule(const WasmSplitOptions& options) { Module wasm; parseInput(wasm, options); @@ -207,7 +207,7 @@ void writePlaceholderMap(const std::map placeholderMap, } } -void splitModule(WasmSplitOptions& options) { +void splitModule(const WasmSplitOptions& options) { Module wasm; parseInput(wasm, options); @@ -430,7 +430,7 @@ void checkExists(const std::string& path) { } } -void printReadableProfile(WasmSplitOptions& options) { +void printReadableProfile(const WasmSplitOptions& options) { const std::string wasmFile(options.inputFiles[0]); checkExists(options.profileFile); checkExists(wasmFile); From a9a4566243dbb90067d9e1c89249cc4f045e176d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 14:33:01 -0700 Subject: [PATCH 55/77] fix --- src/tools/optimization-options.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/tools/optimization-options.h b/src/tools/optimization-options.h index 1a0d1bdc9bb..8772edd29d3 100644 --- a/src/tools/optimization-options.h +++ b/src/tools/optimization-options.h @@ -26,6 +26,17 @@ namespace wasm { struct OptimizationOptions : public ToolOptions { + void parse(int argc, const char* argv[]) { + ToolOptions::parse(argc, argv); + + // After parsing the arguments, update defaults based on the optimize/shrink + // levels. + if (passOptions.optimizeLevel >= 2 || passOptions.shrinkLevel >= 1) { + passOptions.generateStackIR = true; + passOptions.optimizeStackIR = true; + } + } + static constexpr const char* DEFAULT_OPT_PASSES = "O"; static constexpr const int OS_OPTIMIZE_LEVEL = 2; static constexpr const int OS_SHRINK_LEVEL = 1; @@ -56,17 +67,9 @@ struct OptimizationOptions : public ToolOptions { // level, so that the last of -O3 -Os will override the previous default, but // also we note the current opt level for when we run the pass, so that the // sequence -O3 -Os will run -O3 and then -Os, and not -Os twice. - // - // This also applies the consequences of the current optimize and shrink - // levels. void addDefaultOptPasses() { passes.push_back(PassInfo{ DEFAULT_OPT_PASSES, passOptions.optimizeLevel, passOptions.shrinkLevel}); - - if (passOptions.optimizeLevel >= 2 || passOptions.shrinkLevel >= 1) { - passOptions.generateStackIR = true; - passOptions.optimizeStackIR = true; - } } constexpr static const char* OptimizationOptionsCategory = From 8f5b36c6491f4c0070af138d207c841d2512223b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 14:45:06 -0700 Subject: [PATCH 56/77] fix test --- test/unit/test_stack_ir.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/test/unit/test_stack_ir.py b/test/unit/test_stack_ir.py index 78086d0ccee..191d7eaec29 100644 --- a/test/unit/test_stack_ir.py +++ b/test/unit/test_stack_ir.py @@ -7,13 +7,16 @@ class StackIRTest(utils.BinaryenTestCase): # test that stack IR opts make a difference. def test_stack_ir_opts(self): path = self.input_path('stack_ir.wat') - opt = shared.run_process(shared.WASM_OPT + [path, '-O', '--generate-stack-ir', '--optimize-stack-ir', '--print-stack-ir', '-o', 'a.wasm'], capture_output=True).stdout - nonopt = shared.run_process(shared.WASM_OPT + [path, '-O', '--generate-stack-ir', '--print-stack-ir', '-o', 'b.wasm'], capture_output=True).stdout + shared_args = shared.WASM_OPT + [path, '--print-stack-ir'] + # optimize level 2 will only run some of the stack IR opts. level 3 does + # noticeably more. + nonopt = shared.run_process(shared_args + ['-o', 'nonopt.wasm', '--optimize-level=2'], capture_output=True).stdout + yesopt = shared.run_process(shared_args + ['-o', 'yesopt.wasm', '--optimize-level=3'], capture_output=True).stdout # see a difference in the printed stack IR (the optimizations let us # remove a pair of local.set/get) - self.assertNotEqual(opt, nonopt) - self.assertLess(len(opt), len(nonopt)) + self.assertNotEqual(yesopt, nonopt) + self.assertLess(len(yesopt), len(nonopt)) # see a difference in the actual emitted wasm binary. - opt_size = os.path.getsize('a.wasm') - nonopt_size = os.path.getsize('b.wasm') - self.assertLess(opt_size, nonopt_size) + yesopt_size = os.path.getsize('yesopt.wasm') + nonopt_size = os.path.getsize('nonopt.wasm') + self.assertLess(yesopt_size, nonopt_size) From 9221bfb986bd9e4822e2c1d2debd03d62ea3ccb3 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 2 May 2024 16:50:02 -0700 Subject: [PATCH 57/77] fix a manual test --- test/lit/passes/O1_skip.wast | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lit/passes/O1_skip.wast b/test/lit/passes/O1_skip.wast index 2cefecdcf98..54d6a684377 100644 --- a/test/lit/passes/O1_skip.wast +++ b/test/lit/passes/O1_skip.wast @@ -46,7 +46,7 @@ ) ;; CHECK: (export "foo" (func $foo)) -;; CHECK: (func $foo (; has Stack IR ;) (param $p i32) +;; CHECK: (func $foo (param $p i32) ;; CHECK-NEXT: (local $x i32) ;; CHECK-NEXT: (local $y i32) ;; CHECK-NEXT: (call $log From 1fa807717ada925c2de7c430b763825867c1c256 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 3 May 2024 11:16:05 -0700 Subject: [PATCH 58/77] fix --- src/wasm/wasm-binary.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index eca26a6388a..9d9f5b248ff 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -399,6 +399,7 @@ void WasmBinaryWriter::prepareFunctions() { }; PassRunner runner(wasm, options); + runner.setIsNested(true); runner.add(std::make_unique()); runner.run(); From 52028313e5d5cb011e0ebebc345f909edbb6b1e4 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 6 May 2024 13:02:45 -0700 Subject: [PATCH 59/77] better --- src/js/binaryen.js-post.js | 4 ++-- src/passes/Print.cpp | 16 +++++++++++++++- src/tools/wasm-opt.cpp | 2 +- src/wasm-stack.h | 4 ++++ src/wasm/wasm-binary.cpp | 2 +- test/binaryen.js/stackir.js | 3 ++- test/example/c-api-kitchen-sink.c | 7 ++++++- test/example/c-api-kitchen-sink.txt | 10 ++++++++++ 8 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index 1461420bb61..dfde2d7effe 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -2688,8 +2688,8 @@ function wrapModule(module, self = {}) { if (textPtr) _free(textPtr); return text; }; - self['emitStackIR'] = function(optimize) { - let textPtr = Module['_BinaryenModuleAllocateAndWriteStackIR'](module, optimize); + self['emitStackIR'] = function() { + let textPtr = Module['_BinaryenModuleAllocateAndWriteStackIR'](module); let text = UTF8ToString(textPtr); if (textPtr) _free(textPtr); return text; diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 381ebbef4eb..1d591ff35b6 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -3600,13 +3600,27 @@ static std::ostream& printStackIR(StackIR* ir, PrintSExpression& printer) { return o; } -std::ostream& printStackIR(std::ostream& o, Module* module) { +std::ostream& printStackIRInternal(std::ostream& o, Module* module) { wasm::PassRunner runner(module); runner.add(std::make_unique(&o)); runner.run(); return o; } +std::ostream& printStackIR(std::ostream& o, Module* module) { + // Go through binary writing in order to print StackIR. The code will end up + // caling |printStackIRInternal|, above, at the right time. + // FIXME: This prints to stdout atm; wasm-binary.cpp needs to get the stream + // somehow. + PassOptions options; + options.generateStackIR = true; + options.printStackIR = true; + BufferWithRandomAccess buffer; + WasmBinaryWriter writer(module, buffer, options); + writer.write(); + return o; +} + } // namespace wasm namespace std { diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index ada7889dd2e..67b0614f99c 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -359,7 +359,7 @@ int main(int argc, const char* argv[]) { wasm.features.hasExceptionHandling() && experimentalNewEH; // Write the binary to an unused buffer and return the size. - auto computeBinarySize = [&]() { + auto computeBinarySize = [&]() { // TODO share code with Print.cpp, use printStackIR BufferWithRandomAccess buffer; WasmBinaryWriter writer(&wasm, buffer, options.passOptions); writer.write(); diff --git a/src/wasm-stack.h b/src/wasm-stack.h index 0911148f8e3..e0d3a906194 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -553,6 +553,10 @@ class StackIROptimizer { bool canRemoveSetGetPair(Index setIndex, Index getIndex); }; +// Emit StackIR when it already exists. This is only used internally. +std::ostream& printStackIRInternal(std::ostream& o, Module* module); + +// Generate and emit StackIR. std::ostream& printStackIR(std::ostream& o, Module* module); } // namespace wasm diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 9d9f5b248ff..55726254e39 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -404,7 +404,7 @@ void WasmBinaryWriter::prepareFunctions() { runner.run(); if (options.printStackIR) { - printStackIR(std::cout, wasm); + printStackIRInternal(std::cout, wasm); } } diff --git a/test/binaryen.js/stackir.js b/test/binaryen.js/stackir.js index d797aa6d818..527b6a47989 100644 --- a/test/binaryen.js/stackir.js +++ b/test/binaryen.js/stackir.js @@ -26,4 +26,5 @@ console.log("=== default ==="); console.log(module.emitStackIR()); console.log("=== optimize ==="); // should omit the second block -console.log(module.emitStackIR(true)); +module.setOptimizeLevel(2); +console.log(module.emitStackIR()); diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index e5b614becbe..66cf43290f7 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -2008,12 +2008,17 @@ void test_binaries() { BinaryenModuleWriteText(module, buffer, 1024); printf("module s-expr printed (in memory):\n%s\n", buffer); - // writ the s-expr representation to a pointer which is managed by the + // write the s-expr representation to a pointer which is managed by the // caller char* text = BinaryenModuleAllocateAndWriteText(module); printf("module s-expr printed (in memory, caller-owned):\n%s\n", text); free(text); + // write StackIR + text = BinaryenModuleAllocateAndWriteStackIR(module); + printf("module s-expr printed (StackIR):\n%s\n", text); + free(text); + BinaryenModuleDispose(module); } diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index 8bdf1ba52ea..ca2d738da2d 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -3140,6 +3140,16 @@ module s-expr printed (in memory, caller-owned): ) ) +(module + (type $0 (func (param i32 i32) (result i32))) + (func $adder (param $0 i32) (param $1 i32) (result i32) + local.get $0 + local.get $1 + i32.add + ) +) +module s-expr printed (StackIR): + (module (type $0 (func (param i32))) (type $1 (func)) From 15bcb6239bff95403c0aa3a55e2cd6228fcae655 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 6 May 2024 13:05:35 -0700 Subject: [PATCH 60/77] print StackIR to any stream --- src/pass.h | 6 +++--- src/passes/Print.cpp | 4 +--- src/tools/tool-options.h | 4 ++-- src/tools/wasm-opt.cpp | 2 +- src/wasm/wasm-binary.cpp | 2 +- test/example/c-api-kitchen-sink.txt | 2 +- 6 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/pass.h b/src/pass.h index 3fa98b6ca2c..ab060309b4b 100644 --- a/src/pass.h +++ b/src/pass.h @@ -226,9 +226,9 @@ struct PassOptions { // on other optimization flags like optimizeLevel. This is on by default in // -O2 and above. bool optimizeStackIR = false; - // Whether to print StackIR during binary writing. This is mainly useful for - // debugging. - bool printStackIR = false; + // Whether to print StackIR during binary writing, and if so to what stream. + // This is mainly useful for debugging. + std::optional printStackIR; // Whether we are targeting JS. In that case we want to avoid emitting things // in the optimizer that do not translate well to JS, or that could cause us // to need extra lowering work or even a loop (where we optimize to something diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 1d591ff35b6..852c168c357 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -3610,11 +3610,9 @@ std::ostream& printStackIRInternal(std::ostream& o, Module* module) { std::ostream& printStackIR(std::ostream& o, Module* module) { // Go through binary writing in order to print StackIR. The code will end up // caling |printStackIRInternal|, above, at the right time. - // FIXME: This prints to stdout atm; wasm-binary.cpp needs to get the stream - // somehow. PassOptions options; options.generateStackIR = true; - options.printStackIR = true; + options.printStackIR = &o; BufferWithRandomAccess buffer; WasmBinaryWriter writer(module, buffer, options); writer.write(); diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h index 75ac14a442c..d87972e6bf6 100644 --- a/src/tools/tool-options.h +++ b/src/tools/tool-options.h @@ -1,4 +1,4 @@ -/* + /* * Copyright 2018 WebAssembly Community Group participants * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -178,7 +178,7 @@ struct ToolOptions : public Options { [&](Options* o, const std::string& arguments) { // Also generate StackIR, to have something to print. passOptions.generateStackIR = true; - passOptions.printStackIR = true; + passOptions.printStackIR = &std::cout; }); } diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index 67b0614f99c..ada7889dd2e 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -359,7 +359,7 @@ int main(int argc, const char* argv[]) { wasm.features.hasExceptionHandling() && experimentalNewEH; // Write the binary to an unused buffer and return the size. - auto computeBinarySize = [&]() { // TODO share code with Print.cpp, use printStackIR + auto computeBinarySize = [&]() { BufferWithRandomAccess buffer; WasmBinaryWriter writer(&wasm, buffer, options.passOptions); writer.write(); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 55726254e39..abc80d955d8 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -404,7 +404,7 @@ void WasmBinaryWriter::prepareFunctions() { runner.run(); if (options.printStackIR) { - printStackIRInternal(std::cout, wasm); + printStackIRInternal(**options.printStackIR, wasm); } } diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index ca2d738da2d..fe784a453aa 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -3140,6 +3140,7 @@ module s-expr printed (in memory, caller-owned): ) ) +module s-expr printed (StackIR): (module (type $0 (func (param i32 i32) (result i32))) (func $adder (param $0 i32) (param $1 i32) (result i32) @@ -3148,7 +3149,6 @@ module s-expr printed (in memory, caller-owned): i32.add ) ) -module s-expr printed (StackIR): (module (type $0 (func (param i32))) From 9304e65f70799995fec98f401aad2562357ece48 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 6 May 2024 13:17:38 -0700 Subject: [PATCH 61/77] fix --- src/tools/tool-options.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h index d87972e6bf6..599b3b22cc3 100644 --- a/src/tools/tool-options.h +++ b/src/tools/tool-options.h @@ -1,4 +1,4 @@ - /* +/* * Copyright 2018 WebAssembly Community Group participants * * Licensed under the Apache License, Version 2.0 (the "License"); From f82e81c164adab8734cfb8bf9ee48e73c91f48cd Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 6 May 2024 14:01:17 -0700 Subject: [PATCH 62/77] fix test --- test/binaryen.js/stackir.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/binaryen.js/stackir.js b/test/binaryen.js/stackir.js index 527b6a47989..dd503a53da4 100644 --- a/test/binaryen.js/stackir.js +++ b/test/binaryen.js/stackir.js @@ -26,5 +26,5 @@ console.log("=== default ==="); console.log(module.emitStackIR()); console.log("=== optimize ==="); // should omit the second block -module.setOptimizeLevel(2); +binaryen.setOptimizeLevel(2); console.log(module.emitStackIR()); From adc9d72225be7e0b870dc4506dd1139a5f5ecb90 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 8 May 2024 14:50:51 -0700 Subject: [PATCH 63/77] Update src/passes/Print.cpp Co-authored-by: Thomas Lively --- src/passes/Print.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 852c168c357..bc13a138231 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -3609,7 +3609,7 @@ std::ostream& printStackIRInternal(std::ostream& o, Module* module) { std::ostream& printStackIR(std::ostream& o, Module* module) { // Go through binary writing in order to print StackIR. The code will end up - // caling |printStackIRInternal|, above, at the right time. + // calling |printStackIRInternal|, above, at the right time. PassOptions options; options.generateStackIR = true; options.printStackIR = &o; From 7a0699c9c582c8db537591c21dccd589a5aa7794 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 May 2024 10:37:57 -0700 Subject: [PATCH 64/77] another suggestion --- src/wasm/wasm-binary.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 4b21987aee4..fb9550688a0 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -387,8 +387,7 @@ void WasmBinaryWriter::prepareFunctions() { void doWalkFunction(Function* func) { StackIRGenerator stackIRGen(*getModule(), func); stackIRGen.write(); - func->stackIR = std::make_unique(); - func->stackIR->swap(stackIRGen.getStackIR()); + func->stackIR = std::make_unique(std::move(stackIRGen.getStackIR())); auto& options = getPassOptions(); if (options.optimizeStackIR) { From 4bab5c69532625880c24f5a33e439921a9361f78 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 May 2024 10:55:10 -0700 Subject: [PATCH 65/77] start on a new journey --- src/wasm-binary.h | 1 - src/wasm-stack.h | 79 +++++++++++++++++++++------------------- src/wasm.h | 20 ---------- src/wasm/wasm-binary.cpp | 47 ++++-------------------- src/wasm/wasm-stack.cpp | 45 ++++++++++++++++++++++- 5 files changed, 94 insertions(+), 98 deletions(-) diff --git a/src/wasm-binary.h b/src/wasm-binary.h index a27be440806..b5aa83960bb 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1316,7 +1316,6 @@ class WasmBinaryWriter { void writeFunctionSignatures(); void writeExpression(Expression* curr); - void prepareFunctions(); void writeFunctions(); void writeStrings(); void writeGlobals(); diff --git a/src/wasm-stack.h b/src/wasm-stack.h index 83cd11c6e0a..f1ab0f96f78 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -18,6 +18,7 @@ #define wasm_stack_h #include "ir/branch-utils.h" +#include "ir/module-utils.h" #include "ir/properties.h" #include "pass.h" #include "support/insert_ordered.h" @@ -85,6 +86,8 @@ class StackInst { Type type; }; +using StackIR = std::vector; + class BinaryInstWriter : public OverriddenVisitor { public: BinaryInstWriter(WasmBinaryWriter& parent, @@ -468,45 +471,40 @@ class BinaryenIRToBinaryWriter bool sourceMap; }; -// Binaryen IR to stack IR converter -// Queues the expressions linearly in Stack IR (SIR) -class StackIRGenerator : public BinaryenIRWriter { -public: - StackIRGenerator(Module& module, Function* func) - : BinaryenIRWriter(func), module(module) {} +// Binaryen IR to stack IR converter for an entire module. Generates all the +// StackIR in parallel, and then allows querying for the StackIR of individual +// functions. +class ModuleStackIRGenerator { + ModuleUtils::ParallelFunctionAnalysis analysis; - void emit(Expression* curr); - void emitScopeEnd(Expression* curr); - void emitHeader() {} - void emitIfElse(If* curr) { - stackIR.push_back(makeStackInst(StackInst::IfElse, curr)); - } - void emitCatch(Try* curr, Index i) { - stackIR.push_back(makeStackInst(StackInst::Catch, curr)); - } - void emitCatchAll(Try* curr) { - stackIR.push_back(makeStackInst(StackInst::CatchAll, curr)); - } - void emitDelegate(Try* curr) { - stackIR.push_back(makeStackInst(StackInst::Delegate, curr)); - } - void emitFunctionEnd() {} - void emitUnreachable() { - stackIR.push_back(makeStackInst(Builder(module).makeUnreachable())); - } - void emitDebugLocation(Expression* curr) {} - - StackIR& getStackIR() { return stackIR; } - -private: - StackInst* makeStackInst(StackInst::Op op, Expression* origin); - StackInst* makeStackInst(Expression* origin) { - return makeStackInst(StackInst::Basic, origin); +public: + ModuleStackIRGenerator(Module& wasm, const PassOptions& options) : analysis( + wasm, [&](Function* func, StackIR& stackIR) { + if (func->imported()) { + return; + } + + StackIRGenerator stackIRGen(*getModule(), func); + stackIRGen.write(); + func->stackIR = std::make_unique(std::move(stackIRGen.getStackIR())); + + if (options.optimizeStackIR) { + StackIROptimizer optimizer(func, options, getModule()->features); + optimizer.run(); + } + }) {} + + // Get StackIR for a function, if it exists. (This allows some functions to + // have it and others not, if we add such capability in the future.) + StackIR* getStackIROrNull(Function* func) { + auto iter = analysis.map.find(func); + if (iter == analysis.map.end()) { + return nullptr; + } + return &iter->second; } +} - Module& module; - StackIR stackIR; // filled in write() -}; // Stack IR to binary writer class StackIRToBinaryWriter { @@ -514,10 +512,11 @@ class StackIRToBinaryWriter { StackIRToBinaryWriter(WasmBinaryWriter& parent, BufferWithRandomAccess& o, Function* func, + StackIR& stackIR, bool sourceMap = false, bool DWARF = false) : parent(parent), writer(parent, o, func, sourceMap, DWARF), func(func), - sourceMap(sourceMap) {} + stackIR(stackIR), sourceMap(sourceMap) {} void write(); @@ -527,6 +526,7 @@ class StackIRToBinaryWriter { WasmBinaryWriter& parent; BinaryInstWriter writer; Function* func; + StackIR& stackIR; bool sourceMap; }; @@ -566,4 +566,9 @@ std::ostream& printStackIR(std::ostream& o, Module* module); } // namespace wasm +namespace std { +std::ostream& operator<<(std::ostream& o, wasm::StackInst& inst); +std::ostream& operator<<(std::ostream& o, wasm::StackIR& ir); +} // namespace std + #endif // wasm_stack_h diff --git a/src/wasm.h b/src/wasm.h index d852950e8b3..ebc7b908d60 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -2136,14 +2136,6 @@ struct BinaryLocations { std::unordered_map functions; }; -// Forward declarations of Stack IR, as functions can contain it, see -// the stackIR property. -// Stack IR is a secondary IR to the main IR defined in this file (Binaryen -// IR). See wasm-stack.h. -class StackInst; - -using StackIR = std::vector; - class Function : public Importable { public: HeapType type = HeapType(Signature()); // parameters and return value @@ -2153,16 +2145,6 @@ class Function : public Importable { // The body of the function Expression* body = nullptr; - // If present, this stack IR was generated from the main Binaryen IR body, - // and possibly optimized. If it is present when writing to wasm binary, - // it will be emitted instead of the main Binaryen IR. - // - // Note that no special care is taken to synchronize the two IRs - if you - // emit stack IR and then optimize the main IR, you need to recompute the - // stack IR. The Pass system will throw away Stack IR if a pass is run - // that declares it may modify Binaryen IR. - std::unique_ptr stackIR; - // local names. these are optional. std::unordered_map localNames; std::unordered_map localIndices; @@ -2511,8 +2493,6 @@ std::ostream& operator<<(std::ostream& o, wasm::Function& func); std::ostream& operator<<(std::ostream& o, wasm::Expression& expression); std::ostream& operator<<(std::ostream& o, wasm::ModuleExpression pair); std::ostream& operator<<(std::ostream& o, wasm::ShallowExpression expression); -std::ostream& operator<<(std::ostream& o, wasm::StackInst& inst); -std::ostream& operator<<(std::ostream& o, wasm::StackIR& ir); } // namespace std diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index fb9550688a0..633a154cf8a 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -69,7 +69,6 @@ void WasmBinaryWriter::write() { writeStart(); writeElementSegments(); writeDataCount(); - prepareFunctions(); writeFunctions(); writeDataSegments(); if (debugInfo || emitModuleName) { @@ -371,42 +370,6 @@ void WasmBinaryWriter::writeImports() { finishSection(start); } -void WasmBinaryWriter::prepareFunctions() { - if (!options.generateStackIR) { - return; - } - - // Generate StackIR for functions in parallel, and optimize if requested. - struct StackIRPass : public WalkerPass> { - bool isFunctionParallel() override { return true; } - - std::unique_ptr create() override { - return std::make_unique(); - } - - void doWalkFunction(Function* func) { - StackIRGenerator stackIRGen(*getModule(), func); - stackIRGen.write(); - func->stackIR = std::make_unique(std::move(stackIRGen.getStackIR())); - - auto& options = getPassOptions(); - if (options.optimizeStackIR) { - StackIROptimizer optimizer(func, options, getModule()->features); - optimizer.run(); - } - } - }; - - PassRunner runner(wasm, options); - runner.setIsNested(true); - runner.add(std::make_unique()); - runner.run(); - - if (options.printStackIR) { - printStackIRInternal(**options.printStackIR, wasm); - } -} - void WasmBinaryWriter::writeFunctionSignatures() { if (importInfo->getNumDefinedFunctions() == 0) { return; @@ -429,6 +392,12 @@ void WasmBinaryWriter::writeFunctions() { if (importInfo->getNumDefinedFunctions() == 0) { return; } + + std::optional moduleStackIR; + if (options.generateStackIR) { + moduleStackIR.emplace(wasm, options); + } + BYN_TRACE("== writeFunctions\n"); auto sectionStart = startSection(BinaryConsts::Section::Code); o << U32LEB(importInfo->getNumDefinedFunctions()); @@ -443,9 +412,9 @@ void WasmBinaryWriter::writeFunctions() { size_t start = o.size(); BYN_TRACE("writing" << func->name << std::endl); // Emit Stack IR if present. - if (func->stackIR) { + if (moduleStackIR; auto* stackIR = moduleStackIR->getStackIROrNull(func)) { BYN_TRACE("write Stack IR\n"); - StackIRToBinaryWriter writer(*this, o, func, sourceMap, DWARF); + StackIRToBinaryWriter writer(*this, o, func, *stackIR, sourceMap, DWARF); writer.write(); if (debugInfo) { funcMappedLocals[func->name] = std::move(writer.getMappedLocals()); diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 1ed60abedc0..b10bc01b136 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -22,6 +22,8 @@ namespace wasm { +namespace { + static Name IMPOSSIBLE_CONTINUE("impossible-continue"); void BinaryInstWriter::emitResultType(Type type) { @@ -2805,7 +2807,7 @@ void StackIRToBinaryWriter::write() { writer.mapLocalsAndEmitHeader(); // Stack to track indices of catches within a try SmallVector catchIndexStack; - for (auto* inst : *func->stackIR) { + for (auto* inst : stackIR) { if (!inst) { continue; // a nullptr is just something we can skip } @@ -2870,4 +2872,45 @@ void StackIRToBinaryWriter::write() { writer.emitFunctionEnd(); } +// Queues the expressions linearly in Stack IR (SIR) +class StackIRGenerator : public BinaryenIRWriter { +public: + StackIRGenerator(Module& module, Function* func) + : BinaryenIRWriter(func), module(module) {} + + void emit(Expression* curr); + void emitScopeEnd(Expression* curr); + void emitHeader() {} + void emitIfElse(If* curr) { + stackIR.push_back(makeStackInst(StackInst::IfElse, curr)); + } + void emitCatch(Try* curr, Index i) { + stackIR.push_back(makeStackInst(StackInst::Catch, curr)); + } + void emitCatchAll(Try* curr) { + stackIR.push_back(makeStackInst(StackInst::CatchAll, curr)); + } + void emitDelegate(Try* curr) { + stackIR.push_back(makeStackInst(StackInst::Delegate, curr)); + } + void emitFunctionEnd() {} + void emitUnreachable() { + stackIR.push_back(makeStackInst(Builder(module).makeUnreachable())); + } + void emitDebugLocation(Expression* curr) {} + + StackIR& getStackIR() { return stackIR; } + +private: + StackInst* makeStackInst(StackInst::Op op, Expression* origin); + StackInst* makeStackInst(Expression* origin) { + return makeStackInst(StackInst::Basic, origin); + } + + Module& module; + StackIR stackIR; // filled in write() +}; + +} // anonymous namespace + } // namespace wasm From 58ce966c133d83bd31e5640803f1a544e32268d2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 May 2024 10:58:10 -0700 Subject: [PATCH 66/77] work --- src/ir/module-utils.cpp | 3 --- src/wasm-stack.h | 21 +++------------------ src/wasm/wasm-stack.cpp | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/ir/module-utils.cpp b/src/ir/module-utils.cpp index 8d9e88d182b..e169f0ff1ea 100644 --- a/src/ir/module-utils.cpp +++ b/src/ir/module-utils.cpp @@ -69,9 +69,6 @@ Function* copyFunction(Function* func, ret->base = func->base; ret->noFullInline = func->noFullInline; ret->noPartialInline = func->noPartialInline; - - // TODO: copy Stack IR - assert(!func->stackIR); return out.addFunction(std::move(ret)); } diff --git a/src/wasm-stack.h b/src/wasm-stack.h index f1ab0f96f78..2d808cdda9c 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -475,24 +475,10 @@ class BinaryenIRToBinaryWriter // StackIR in parallel, and then allows querying for the StackIR of individual // functions. class ModuleStackIRGenerator { - ModuleUtils::ParallelFunctionAnalysis analysis; + ModuleUtils::ParallelFunctionAnalysis analysis; public: - ModuleStackIRGenerator(Module& wasm, const PassOptions& options) : analysis( - wasm, [&](Function* func, StackIR& stackIR) { - if (func->imported()) { - return; - } - - StackIRGenerator stackIRGen(*getModule(), func); - stackIRGen.write(); - func->stackIR = std::make_unique(std::move(stackIRGen.getStackIR())); - - if (options.optimizeStackIR) { - StackIROptimizer optimizer(func, options, getModule()->features); - optimizer.run(); - } - }) {} + ModuleStackIRGenerator(Module& wasm, const PassOptions& options); // Get StackIR for a function, if it exists. (This allows some functions to // have it and others not, if we add such capability in the future.) @@ -503,8 +489,7 @@ class ModuleStackIRGenerator { } return &iter->second; } -} - +}; // Stack IR to binary writer class StackIRToBinaryWriter { diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index b10bc01b136..7c49c0afdbb 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2800,6 +2800,22 @@ StackInst* StackIRGenerator::makeStackInst(StackInst::Op op, return ret; } +ModuleStackIRGenerator::ModuleStackIRGenerator(Module& wasm, const PassOptions& options) : analysis( + wasm, [&](Function* func, StackIR& stackIR) { + if (func->imported()) { + return; + } + + StackIRGenerator stackIRGen(*getModule(), func); + stackIRGen.write(); + stackIR = std::make_unique(std::move(stackIRGen.getStackIR())); + + if (options.optimizeStackIR) { + StackIROptimizer optimizer(func, options, getModule()->features); + optimizer.run(); + } + }) {} + void StackIRToBinaryWriter::write() { if (func->prologLocation.size()) { parent.writeDebugLocation(*func->prologLocation.begin()); From f5b3ec0e8fed3c5280e7ccc5a194ff2342315c6a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 May 2024 11:09:29 -0700 Subject: [PATCH 67/77] work --- src/passes/Monomorphize.cpp | 5 ----- src/passes/Print.cpp | 20 ++++++++------------ src/wasm-stack.h | 5 ++--- src/wasm/wasm-binary.cpp | 2 +- src/wasm/wasm-stack.cpp | 2 +- 5 files changed, 12 insertions(+), 22 deletions(-) diff --git a/src/passes/Monomorphize.cpp b/src/passes/Monomorphize.cpp index f8ee4a6e63a..012f247504b 100644 --- a/src/passes/Monomorphize.cpp +++ b/src/passes/Monomorphize.cpp @@ -151,11 +151,6 @@ struct Monomorphize : public Pass { // monomorphizing. // Create a new function with refined parameters as a copy of the original. - // (Note we must clear stack IR on the original: atm we do not have the - // ability to copy stack IR, so we'd hit an internal error. But as we will - // be optimizing the function anyhow, we'd be throwing away stack IR later - // so this isn't a problem.) - func->stackIR.reset(); auto refinedTarget = Names::getValidFunctionName(*module, target); auto* refinedFunc = ModuleUtils::copyFunction(func, *module, refinedTarget); TypeUpdating::updateParamTypes(refinedFunc, refinedTypes, *module); diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 190f92af86d..cf5d871be68 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -111,7 +111,7 @@ struct PrintSExpression : public UnifiedExpressionVisitor { bool full = false; // whether to not elide nodes in output when possible // (like implicit blocks) and to emit types - bool stackIR = false; // whether to print stack IR if it is present + std::optional moduleStackIR; // whether to print stack IR if it is present // (if false, and Stack IR is there, we just // note it exists) @@ -268,7 +268,9 @@ struct PrintSExpression : public UnifiedExpressionVisitor { void setFull(bool full_) { full = full_; } - void setStackIR(bool stackIR_) { stackIR = stackIR_; } + void generateStackIR(const PassOptions& options) { + moduleStackIR.emplace(*currModule, options); + } void setDebugInfo(bool debugInfo_) { debugInfo = debugInfo_; } @@ -3004,7 +3006,9 @@ void PrintSExpression::visitDefinedFunction(Function* curr) { o << maybeNewLine; } // Print the body. - if (!stackIR || !curr->stackIR) { + if (moduleStackIR; auto* stackIR = moduleStackIR->getStackIROrNull(curr)) { + printStackIR(stackIR, *this); + } else { // It is ok to emit a block here, as a function can directly contain a // list, even if our ast avoids that for simplicity. We can just do that // optimization here.. @@ -3018,9 +3022,6 @@ void PrintSExpression::visitDefinedFunction(Function* curr) { printFullLine(curr->body); } assert(controlFlowDepth == 0); - } else { - // Print the stack IR. - printStackIR(curr->stackIR.get(), *this); } if (currFunction->epilogLocation.size()) { // Print last debug location: mix of decIndent and printDebugLocation @@ -3427,8 +3428,8 @@ class PrintStackIR : public Printer { void run(Module* module) override { PrintSExpression print(o); print.setDebugInfo(getPassOptions().debugInfo); - print.setStackIR(true); print.currModule = module; + print.generateStackIR(getPassOptions()); print.visitModule(module); } }; @@ -3664,9 +3665,4 @@ std::ostream& operator<<(std::ostream& o, wasm::StackInst& inst) { return wasm::printStackInst(&inst, o); } -std::ostream& operator<<(std::ostream& o, wasm::StackIR& ir) { - wasm::PrintSExpression printer(o); - return wasm::printStackIR(&ir, printer); -} - } // namespace std diff --git a/src/wasm-stack.h b/src/wasm-stack.h index 2d808cdda9c..5cb9d311515 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -474,11 +474,11 @@ class BinaryenIRToBinaryWriter // Binaryen IR to stack IR converter for an entire module. Generates all the // StackIR in parallel, and then allows querying for the StackIR of individual // functions. -class ModuleStackIRGenerator { +class ModuleStackIR { ModuleUtils::ParallelFunctionAnalysis analysis; public: - ModuleStackIRGenerator(Module& wasm, const PassOptions& options); + ModuleStackIR(Module& wasm, const PassOptions& options); // Get StackIR for a function, if it exists. (This allows some functions to // have it and others not, if we add such capability in the future.) @@ -553,7 +553,6 @@ std::ostream& printStackIR(std::ostream& o, Module* module); namespace std { std::ostream& operator<<(std::ostream& o, wasm::StackInst& inst); -std::ostream& operator<<(std::ostream& o, wasm::StackIR& ir); } // namespace std #endif // wasm_stack_h diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 633a154cf8a..c9245c1b562 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -393,7 +393,7 @@ void WasmBinaryWriter::writeFunctions() { return; } - std::optional moduleStackIR; + std::optional moduleStackIR; if (options.generateStackIR) { moduleStackIR.emplace(wasm, options); } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 7c49c0afdbb..16d69fa1ed0 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2800,7 +2800,7 @@ StackInst* StackIRGenerator::makeStackInst(StackInst::Op op, return ret; } -ModuleStackIRGenerator::ModuleStackIRGenerator(Module& wasm, const PassOptions& options) : analysis( +ModuleStackIR::ModuleStackIR(Module& wasm, const PassOptions& options) : analysis( wasm, [&](Function* func, StackIR& stackIR) { if (func->imported()) { return; From 85ad15e6fa92246ef743cbcbdd99585bf8e815f5 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 May 2024 11:13:24 -0700 Subject: [PATCH 68/77] work --- src/passes/Print.cpp | 6 +++++- src/wasm/wasm-binary.cpp | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index cf5d871be68..fd81a8137f0 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -3006,7 +3006,11 @@ void PrintSExpression::visitDefinedFunction(Function* curr) { o << maybeNewLine; } // Print the body. - if (moduleStackIR; auto* stackIR = moduleStackIR->getStackIROrNull(curr)) { + StackIR* stackIR = nullptr; + if (moduleStackIR) { + stackIR = moduleStackIR->getStackIROrNull(curr); + } + if (stackIR { printStackIR(stackIR, *this); } else { // It is ok to emit a block here, as a function can directly contain a diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index c9245c1b562..eaa5eabb4bb 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -395,7 +395,7 @@ void WasmBinaryWriter::writeFunctions() { std::optional moduleStackIR; if (options.generateStackIR) { - moduleStackIR.emplace(wasm, options); + moduleStackIR.emplace(*wasm, options); } BYN_TRACE("== writeFunctions\n"); @@ -412,7 +412,11 @@ void WasmBinaryWriter::writeFunctions() { size_t start = o.size(); BYN_TRACE("writing" << func->name << std::endl); // Emit Stack IR if present. - if (moduleStackIR; auto* stackIR = moduleStackIR->getStackIROrNull(func)) { + StackIR* stackIR = nullptr; + if (moduleStackIR) { + stackIR = moduleStackIR->getStackIROrNull(func); + } + if (stackIR { BYN_TRACE("write Stack IR\n"); StackIRToBinaryWriter writer(*this, o, func, *stackIR, sourceMap, DWARF); writer.write(); From 670bc3a5a4afa482d11e899fca8a2e97f42ace20 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 May 2024 11:14:57 -0700 Subject: [PATCH 69/77] work --- src/passes/Print.cpp | 2 +- src/wasm-stack.h | 3 ++- src/wasm/wasm-stack-opts.cpp | 7 +++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index fd81a8137f0..f1826ae7001 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -3010,7 +3010,7 @@ void PrintSExpression::visitDefinedFunction(Function* curr) { if (moduleStackIR) { stackIR = moduleStackIR->getStackIROrNull(curr); } - if (stackIR { + if (stackIR) { printStackIR(stackIR, *this); } else { // It is ok to emit a block here, as a function can directly contain a diff --git a/src/wasm-stack.h b/src/wasm-stack.h index 5cb9d311515..3c377b2f055 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -518,12 +518,13 @@ class StackIRToBinaryWriter { // Stack IR optimizer class StackIROptimizer { Function* func; - const PassOptions& passOptions; StackIR& insts; + const PassOptions& passOptions; FeatureSet features; public: StackIROptimizer(Function* func, + StackIR& insts, const PassOptions& passOptions, FeatureSet features); diff --git a/src/wasm/wasm-stack-opts.cpp b/src/wasm/wasm-stack-opts.cpp index f95d1cd45ee..504a9bcc103 100644 --- a/src/wasm/wasm-stack-opts.cpp +++ b/src/wasm/wasm-stack-opts.cpp @@ -27,12 +27,11 @@ namespace wasm { StackIROptimizer::StackIROptimizer(Function* func, + StackIR& insts, const PassOptions& passOptions, FeatureSet features) - : func(func), passOptions(passOptions), insts(*func->stackIR.get()), - features(features) { - assert(func->stackIR); // TODO move out of func -} + : func(func), insts(insts), passOptions(passOptions), + features(features) {} void StackIROptimizer::run() { dce(); From 720e2da83b8a43967cc4b5980421877d2ec756af Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 May 2024 11:18:30 -0700 Subject: [PATCH 70/77] work --- src/wasm/wasm-binary.cpp | 2 +- src/wasm/wasm-stack.cpp | 88 +++++++++++++++++++--------------------- 2 files changed, 43 insertions(+), 47 deletions(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index eaa5eabb4bb..7e90dfde4d3 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -416,7 +416,7 @@ void WasmBinaryWriter::writeFunctions() { if (moduleStackIR) { stackIR = moduleStackIR->getStackIROrNull(func); } - if (stackIR { + if (stackIR) { BYN_TRACE("write Stack IR\n"); StackIRToBinaryWriter writer(*this, o, func, *stackIR, sourceMap, DWARF); writer.write(); diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 16d69fa1ed0..f3c9867832d 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -22,8 +22,6 @@ namespace wasm { -namespace { - static Name IMPOSSIBLE_CONTINUE("impossible-continue"); void BinaryInstWriter::emitResultType(Type type) { @@ -2739,6 +2737,45 @@ int32_t BinaryInstWriter::getBreakIndex(Name name) { // -1 if not found WASM_UNREACHABLE("break index not found"); } +// Queues the expressions linearly in Stack IR (SIR) +class StackIRGenerator : public BinaryenIRWriter { +public: + StackIRGenerator(Module& module, Function* func) + : BinaryenIRWriter(func), module(module) {} + + void emit(Expression* curr); + void emitScopeEnd(Expression* curr); + void emitHeader() {} + void emitIfElse(If* curr) { + stackIR.push_back(makeStackInst(StackInst::IfElse, curr)); + } + void emitCatch(Try* curr, Index i) { + stackIR.push_back(makeStackInst(StackInst::Catch, curr)); + } + void emitCatchAll(Try* curr) { + stackIR.push_back(makeStackInst(StackInst::CatchAll, curr)); + } + void emitDelegate(Try* curr) { + stackIR.push_back(makeStackInst(StackInst::Delegate, curr)); + } + void emitFunctionEnd() {} + void emitUnreachable() { + stackIR.push_back(makeStackInst(Builder(module).makeUnreachable())); + } + void emitDebugLocation(Expression* curr) {} + + StackIR& getStackIR() { return stackIR; } + +private: + StackInst* makeStackInst(StackInst::Op op, Expression* origin); + StackInst* makeStackInst(Expression* origin) { + return makeStackInst(StackInst::Basic, origin); + } + + Module& module; + StackIR stackIR; // filled in write() +}; + void StackIRGenerator::emit(Expression* curr) { StackInst* stackInst = nullptr; if (curr->is()) { @@ -2806,12 +2843,12 @@ ModuleStackIR::ModuleStackIR(Module& wasm, const PassOptions& options) : analysi return; } - StackIRGenerator stackIRGen(*getModule(), func); + StackIRGenerator stackIRGen(wasm, func); stackIRGen.write(); - stackIR = std::make_unique(std::move(stackIRGen.getStackIR())); + stackIR = std::move(stackIRGen.getStackIR()); if (options.optimizeStackIR) { - StackIROptimizer optimizer(func, options, getModule()->features); + StackIROptimizer optimizer(func, options, wasm.features); optimizer.run(); } }) {} @@ -2888,45 +2925,4 @@ void StackIRToBinaryWriter::write() { writer.emitFunctionEnd(); } -// Queues the expressions linearly in Stack IR (SIR) -class StackIRGenerator : public BinaryenIRWriter { -public: - StackIRGenerator(Module& module, Function* func) - : BinaryenIRWriter(func), module(module) {} - - void emit(Expression* curr); - void emitScopeEnd(Expression* curr); - void emitHeader() {} - void emitIfElse(If* curr) { - stackIR.push_back(makeStackInst(StackInst::IfElse, curr)); - } - void emitCatch(Try* curr, Index i) { - stackIR.push_back(makeStackInst(StackInst::Catch, curr)); - } - void emitCatchAll(Try* curr) { - stackIR.push_back(makeStackInst(StackInst::CatchAll, curr)); - } - void emitDelegate(Try* curr) { - stackIR.push_back(makeStackInst(StackInst::Delegate, curr)); - } - void emitFunctionEnd() {} - void emitUnreachable() { - stackIR.push_back(makeStackInst(Builder(module).makeUnreachable())); - } - void emitDebugLocation(Expression* curr) {} - - StackIR& getStackIR() { return stackIR; } - -private: - StackInst* makeStackInst(StackInst::Op op, Expression* origin); - StackInst* makeStackInst(Expression* origin) { - return makeStackInst(StackInst::Basic, origin); - } - - Module& module; - StackIR stackIR; // filled in write() -}; - -} // anonymous namespace - } // namespace wasm From 9e5d4ccac7c4d362f76f42006d3e287770a7a069 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 May 2024 11:19:21 -0700 Subject: [PATCH 71/77] work --- src/wasm/wasm-stack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index f3c9867832d..670b0337e52 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2848,7 +2848,7 @@ ModuleStackIR::ModuleStackIR(Module& wasm, const PassOptions& options) : analysi stackIR = std::move(stackIRGen.getStackIR()); if (options.optimizeStackIR) { - StackIROptimizer optimizer(func, options, wasm.features); + StackIROptimizer optimizer(func, stackIR, options, wasm.features); optimizer.run(); } }) {} From 936f4699815b6ca32398a305df5a47a140ab3124 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 May 2024 11:31:06 -0700 Subject: [PATCH 72/77] fix --- src/passes/Print.cpp | 16 +--------------- src/tools/wasm-opt.cpp | 3 ++- src/wasm-stack.h | 3 --- 3 files changed, 3 insertions(+), 19 deletions(-) diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index f1826ae7001..e6d4548980b 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -3438,8 +3438,6 @@ class PrintStackIR : public Printer { } }; -Pass* createPrintStackIRPass() { return new PrintStackIR(); } - static std::ostream& printExpression(Expression* expression, std::ostream& o, bool minify, @@ -3604,25 +3602,13 @@ static std::ostream& printStackIR(StackIR* ir, PrintSExpression& printer) { return o; } -std::ostream& printStackIRInternal(std::ostream& o, Module* module) { +std::ostream& printStackIR(std::ostream& o, Module* module) { wasm::PassRunner runner(module); runner.add(std::make_unique(&o)); runner.run(); return o; } -std::ostream& printStackIR(std::ostream& o, Module* module) { - // Go through binary writing in order to print StackIR. The code will end up - // calling |printStackIRInternal|, above, at the right time. - PassOptions options; - options.generateStackIR = true; - options.printStackIR = &o; - BufferWithRandomAccess buffer; - WasmBinaryWriter writer(module, buffer, options); - writer.write(); - return o; -} - } // namespace wasm namespace std { diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index ada7889dd2e..6a78f3159ef 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -35,6 +35,7 @@ #include "wasm-interpreter.h" #include "wasm-io.h" #include "wasm-s-parser.h" +#include "wasm-stack.h" #include "wasm-validator.h" #include "wasm2c-wrapper.h" @@ -423,7 +424,7 @@ int main(int argc, const char* argv[]) { // are not emitting a binary, but we do want to go through the binary // writing process just to get StackIR to be printed. We can do that by // computing the binary size. - computeBinarySize(); + printStackIR(std::cout, &wasm); } if (!options.quiet) { std::cerr << "warning: no output file specified, not emitting output\n"; diff --git a/src/wasm-stack.h b/src/wasm-stack.h index 3c377b2f055..fa0ff33b73f 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -544,9 +544,6 @@ class StackIROptimizer { bool canRemoveSetGetPair(Index setIndex, Index getIndex); }; -// Emit StackIR when it already exists. This is only used internally. -std::ostream& printStackIRInternal(std::ostream& o, Module* module); - // Generate and emit StackIR. std::ostream& printStackIR(std::ostream& o, Module* module); From 9f16e4f647d2b6c1af9b3f72fe4cd9cf70114485 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 May 2024 11:54:44 -0700 Subject: [PATCH 73/77] work --- src/binaryen-c.cpp | 6 +++--- src/passes/Print.cpp | 4 ++-- src/tools/wasm-opt.cpp | 2 +- src/wasm-stack.h | 2 +- src/wasm/wasm-stack.cpp | 2 ++ 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index f42644047de..1c9a5be0e76 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -5591,7 +5591,7 @@ void BinaryenModulePrint(BinaryenModuleRef module) { } void BinaryenModulePrintStackIR(BinaryenModuleRef module) { - wasm::printStackIR(std::cout, (Module*)module); + wasm::printStackIR(std::cout, (Module*)module, globalPassOptions); } void BinaryenModulePrintAsmjs(BinaryenModuleRef module) { @@ -5782,7 +5782,7 @@ size_t BinaryenModuleWriteStackIR(BinaryenModuleRef module, // use a stringstream as an std::ostream. Extract the std::string // representation, and then store in the output. std::stringstream ss; - wasm::printStackIR(ss, (Module*)module); + wasm::printStackIR(ss, (Module*)module, globalPassOptions); const auto temp = ss.str(); const auto ctemp = temp.c_str(); @@ -5846,7 +5846,7 @@ char* BinaryenModuleAllocateAndWriteStackIR(BinaryenModuleRef module) { bool colors = Colors::isEnabled(); Colors::setEnabled(false); // do not use colors for writing - wasm::printStackIR(os, (Module*)module); + wasm::printStackIR(os, (Module*)module, globalPassOptions); Colors::setEnabled(colors); // restore colors state auto str = os.str(); diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index e6d4548980b..df31219dd5f 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -3602,8 +3602,8 @@ static std::ostream& printStackIR(StackIR* ir, PrintSExpression& printer) { return o; } -std::ostream& printStackIR(std::ostream& o, Module* module) { - wasm::PassRunner runner(module); +std::ostream& printStackIR(std::ostream& o, Module* module, const PassOptions& options) { + wasm::PassRunner runner(module, options); runner.add(std::make_unique(&o)); runner.run(); return o; diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index 6a78f3159ef..e512eea9796 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -424,7 +424,7 @@ int main(int argc, const char* argv[]) { // are not emitting a binary, but we do want to go through the binary // writing process just to get StackIR to be printed. We can do that by // computing the binary size. - printStackIR(std::cout, &wasm); + printStackIR(std::cout, &wasm, options.passOptions); } if (!options.quiet) { std::cerr << "warning: no output file specified, not emitting output\n"; diff --git a/src/wasm-stack.h b/src/wasm-stack.h index fa0ff33b73f..86aa59b3f54 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -545,7 +545,7 @@ class StackIROptimizer { }; // Generate and emit StackIR. -std::ostream& printStackIR(std::ostream& o, Module* module); +std::ostream& printStackIR(std::ostream& o, Module* module, const PassOptions& options); } // namespace wasm diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 670b0337e52..c809cd5071c 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2846,8 +2846,10 @@ ModuleStackIR::ModuleStackIR(Module& wasm, const PassOptions& options) : analysi StackIRGenerator stackIRGen(wasm, func); stackIRGen.write(); stackIR = std::move(stackIRGen.getStackIR()); +std::cout << "gen\n"; if (options.optimizeStackIR) { +std::cout << "opt\n"; StackIROptimizer optimizer(func, stackIR, options, wasm.features); optimizer.run(); } From 94d2efafbb942ecdaf60ed0c36cc2bc252417e3b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 May 2024 11:55:30 -0700 Subject: [PATCH 74/77] work --- src/wasm/wasm-stack.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index c809cd5071c..670b0337e52 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2846,10 +2846,8 @@ ModuleStackIR::ModuleStackIR(Module& wasm, const PassOptions& options) : analysi StackIRGenerator stackIRGen(wasm, func); stackIRGen.write(); stackIR = std::move(stackIRGen.getStackIR()); -std::cout << "gen\n"; if (options.optimizeStackIR) { -std::cout << "opt\n"; StackIROptimizer optimizer(func, stackIR, options, wasm.features); optimizer.run(); } From f572bddce2fb4e2bc8206fa9a9eeb9e12df9d193 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 May 2024 12:00:18 -0700 Subject: [PATCH 75/77] format --- src/passes/Print.cpp | 13 +++++++------ src/wasm-stack.h | 3 ++- src/wasm/wasm-stack-opts.cpp | 3 +-- src/wasm/wasm-stack.cpp | 4 ++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index df31219dd5f..99c86cec472 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -109,11 +109,11 @@ struct PrintSExpression : public UnifiedExpressionVisitor { const char* maybeSpace; const char* maybeNewLine; - bool full = false; // whether to not elide nodes in output when possible - // (like implicit blocks) and to emit types - std::optional moduleStackIR; // whether to print stack IR if it is present - // (if false, and Stack IR is there, we just - // note it exists) + // Whether to not elide nodes in output when possible (like implicit blocks) + // and to emit types. + bool full = false; + // If present, it contains StackIR that we will print. + std::optional moduleStackIR; Module* currModule = nullptr; Function* currFunction = nullptr; @@ -3602,7 +3602,8 @@ static std::ostream& printStackIR(StackIR* ir, PrintSExpression& printer) { return o; } -std::ostream& printStackIR(std::ostream& o, Module* module, const PassOptions& options) { +std::ostream& +printStackIR(std::ostream& o, Module* module, const PassOptions& options) { wasm::PassRunner runner(module, options); runner.add(std::make_unique(&o)); runner.run(); diff --git a/src/wasm-stack.h b/src/wasm-stack.h index 86aa59b3f54..ae453f9de3e 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -545,7 +545,8 @@ class StackIROptimizer { }; // Generate and emit StackIR. -std::ostream& printStackIR(std::ostream& o, Module* module, const PassOptions& options); +std::ostream& +printStackIR(std::ostream& o, Module* module, const PassOptions& options); } // namespace wasm diff --git a/src/wasm/wasm-stack-opts.cpp b/src/wasm/wasm-stack-opts.cpp index 504a9bcc103..eac423fbd18 100644 --- a/src/wasm/wasm-stack-opts.cpp +++ b/src/wasm/wasm-stack-opts.cpp @@ -30,8 +30,7 @@ StackIROptimizer::StackIROptimizer(Function* func, StackIR& insts, const PassOptions& passOptions, FeatureSet features) - : func(func), insts(insts), passOptions(passOptions), - features(features) {} + : func(func), insts(insts), passOptions(passOptions), features(features) {} void StackIROptimizer::run() { dce(); diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 670b0337e52..3cdd1f71814 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2837,8 +2837,8 @@ StackInst* StackIRGenerator::makeStackInst(StackInst::Op op, return ret; } -ModuleStackIR::ModuleStackIR(Module& wasm, const PassOptions& options) : analysis( - wasm, [&](Function* func, StackIR& stackIR) { +ModuleStackIR::ModuleStackIR(Module& wasm, const PassOptions& options) + : analysis(wasm, [&](Function* func, StackIR& stackIR) { if (func->imported()) { return; } From 3369186540ff8a73acfcda07d48833f8af783825 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 May 2024 12:26:39 -0700 Subject: [PATCH 76/77] bettr --- src/tools/wasm-opt.cpp | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index e512eea9796..7d4558fdc3f 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -359,14 +359,6 @@ int main(int argc, const char* argv[]) { bool translateToNewEH = wasm.features.hasExceptionHandling() && experimentalNewEH; - // Write the binary to an unused buffer and return the size. - auto computeBinarySize = [&]() { - BufferWithRandomAccess buffer; - WasmBinaryWriter writer(&wasm, buffer, options.passOptions); - writer.write(); - return buffer.size(); - }; - if (!options.runningPasses()) { if (!options.quiet && !translateToNewEH) { std::cerr << "warning: no passes specified, not doing any work\n"; @@ -386,11 +378,17 @@ int main(int argc, const char* argv[]) { if (converge) { // Keep on running passes to convergence, defined as binary // size no longer decreasing. - auto lastSize = computeBinarySize(); + auto getSize = [&]() { + BufferWithRandomAccess buffer; + WasmBinaryWriter writer(&wasm, buffer); + writer.write(); + return buffer.size(); + }; + auto lastSize = getSize(); while (1) { BYN_TRACE("running iteration for convergence (" << lastSize << ")..\n"); runPasses(); - auto currSize = computeBinarySize(); + auto currSize = getSize(); if (currSize >= lastSize) { break; } @@ -418,14 +416,11 @@ int main(int argc, const char* argv[]) { results.check(wasm); } + if (options.passOptions.printStackIR) { + printStackIR(std::cout, &wasm, options.passOptions); + } + if (options.extra.count("output") == 0) { - if (options.passOptions.printStackIR) { - // The user asked to print StackIR without setting an output file, so we - // are not emitting a binary, but we do want to go through the binary - // writing process just to get StackIR to be printed. We can do that by - // computing the binary size. - printStackIR(std::cout, &wasm, options.passOptions); - } if (!options.quiet) { std::cerr << "warning: no output file specified, not emitting output\n"; } From b9750e392e8ba0ad43431d86d85402d976b3c87b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 9 May 2024 12:32:05 -0700 Subject: [PATCH 77/77] fix --- src/tools/wasm-opt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index 7d4558fdc3f..cb6d0bcec56 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -380,7 +380,7 @@ int main(int argc, const char* argv[]) { // size no longer decreasing. auto getSize = [&]() { BufferWithRandomAccess buffer; - WasmBinaryWriter writer(&wasm, buffer); + WasmBinaryWriter writer(&wasm, buffer, options.passOptions); writer.write(); return buffer.size(); };