diff options
-rwxr-xr-x | scripts/fuzz_opt.py | 1 | ||||
-rw-r--r-- | src/ir/module-utils.h | 12 | ||||
-rw-r--r-- | src/passes/Inlining.cpp | 628 | ||||
-rw-r--r-- | test/lit/passes/inlining-optimizing_optimize-level=3.wast | 1201 | ||||
-rw-r--r-- | test/lit/passes/inlining_splitting.wast | 1702 |
5 files changed, 2921 insertions, 623 deletions
diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py index 73de5d8e2..abc6225ee 100755 --- a/scripts/fuzz_opt.py +++ b/scripts/fuzz_opt.py @@ -176,6 +176,7 @@ IMPORTANT_INITIAL_CONTENTS = [ os.path.join('lit', 'passes', 'optimize-instructions-bulk-memory.wast'), os.path.join('lit', 'passes', 'optimize-instructions-ignore-traps.wast'), os.path.join('lit', 'passes', 'optimize-instructions-gc.wast'), + os.path.join('lit', 'passes', 'inlining_splitting.wast'), ] IMPORTANT_INITIAL_CONTENTS = [os.path.join(shared.get_test_dir('.'), t) for t in IMPORTANT_INITIAL_CONTENTS] diff --git a/src/ir/module-utils.h b/src/ir/module-utils.h index d916f51a2..d191a35f1 100644 --- a/src/ir/module-utils.h +++ b/src/ir/module-utils.h @@ -30,9 +30,12 @@ namespace wasm { namespace ModuleUtils { -inline Function* copyFunction(Function* func, Module& out) { - auto* ret = new Function(); - ret->name = func->name; +// Copies a function into a module. If newName is provided it is used as the +// name of the function (otherwise the original name is copied). +inline Function* +copyFunction(Function* func, Module& out, Name newName = Name()) { + auto ret = std::make_unique<Function>(); + ret->name = newName.is() ? newName : func->name; ret->type = func->type; ret->vars = func->vars; ret->localNames = func->localNames; @@ -43,8 +46,7 @@ inline Function* copyFunction(Function* func, Module& out) { ret->base = func->base; // TODO: copy Stack IR assert(!func->stackIR); - out.addFunction(ret); - return ret; + return out.addFunction(std::move(ret)); } inline Global* copyGlobal(Global* global, Module& out) { diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp index 11e9c5a2c..18b3d562a 100644 --- a/src/passes/Inlining.cpp +++ b/src/passes/Inlining.cpp @@ -30,10 +30,12 @@ #include <atomic> +#include "ir/branch-utils.h" #include "ir/debug.h" #include "ir/element-utils.h" #include "ir/literal-utils.h" #include "ir/module-utils.h" +#include "ir/names.h" #include "ir/type-updating.h" #include "ir/utils.h" #include "parsing.h" @@ -44,6 +46,8 @@ namespace wasm { +namespace { + // Useful into on a function, helping us decide if we can inline it struct FunctionInfo { std::atomic<Index> refs; @@ -54,7 +58,9 @@ struct FunctionInfo { bool usedGlobally; // in a table or export bool uninlineable; - FunctionInfo() { + FunctionInfo() { clear(); } + + void clear() { refs = 0; size = 0; hasCalls = false; @@ -64,6 +70,18 @@ struct FunctionInfo { uninlineable = false; } + // Provide an explicit = operator as the |refs| field lacks one by default. + FunctionInfo& operator=(FunctionInfo& other) { + refs = other.refs.load(); + size = other.size; + hasCalls = other.hasCalls; + hasLoops = other.hasLoops; + hasTryDelegate = other.hasTryDelegate; + usedGlobally = other.usedGlobally; + uninlineable = other.uninlineable; + return *this; + } + // See pass.h for how defaults for these options were chosen. bool worthInlining(PassOptions& options) { if (uninlineable) { @@ -102,6 +120,17 @@ struct FunctionInfo { } }; +static bool canHandleParams(Function* func) { + // We cannot inline a function if we cannot handle placing its params in a + // locals, as all params become locals. + for (auto param : func->getParams()) { + if (!TypeUpdating::canHandleAsLocal(param)) { + return false; + } + } + return true; +} + typedef std::unordered_map<Name, FunctionInfo> NameInfoMap; struct FunctionInfoScanner @@ -149,12 +178,8 @@ struct FunctionInfoScanner void visitFunction(Function* curr) { auto& info = (*infos)[curr->name]; - // We cannot inline a function if we cannot handle placing it in a local, as - // all params become locals. - for (auto param : curr->getParams()) { - if (!TypeUpdating::canHandleAsLocal(param)) { - info.uninlineable = true; - } + if (!canHandleParams(curr)) { + info.uninlineable = true; } info.size = Measurer::measure(curr->body); @@ -332,6 +357,439 @@ doInlining(Module* module, Function* into, const InliningAction& action) { return block; } +// +// Function splitting / partial inlining / inlining of conditions. +// +// A function may be too costly to inline, but it may be profitable to +// *partially* inline it. The specific cases optimized here are functions with a +// condition, +// +// function foo(x) { +// if (x) return; +// ..lots and lots of other code.. +// } +// +// If the other code after the if is large enough or costly enough, then we will +// not inline the entire function. But it is useful to inline the condition. +// Consider this caller: +// +// function caller(x) { +// foo(0); +// foo(x); +// } +// +// If we inline the condition, we end up with this: +// +// function caller(x) { +// if (0) foo(0); +// if (x) foo(x); +// } +// +// By inlining the condition out of foo() we gain two benefits: +// +// * In the first call here the condition is zero, which means we can +// statically optimize out the call entirely. +// * Even if we can't do that (as in the second call) if at runtime we see the +// condition is false then we avoid the call. That means we perform what is +// hopefully a cheap branch instead of a call and then a branch. +// +// The cost to doing this is an increase in code size, and so this is only done +// when optimizing heavily for speed. +// +// To implement partial inlining we split the function to be inlined. Starting +// with +// +// function foo(x) { +// if (x) return; +// ..lots and lots of other code.. +// } +// +// We create the "inlineable" part of it, and the code that is "outlined": +// +// function foo$inlineable(x) { +// if (x) return; +// foo$outlined(x); +// } +// function foo$outlined(x) { +// ..lots and lots of other code.. +// } +// +// (Note how if the second function were inlined into the first, we would end +// up where we started, with the original function.) After splitting the +// function in this way, we simply inline the inlineable part using the normal +// mechanism for that. That ends up replacing foo(x); with +// +// if (x) foo$outlined(x); +// +// which is what we wanted. +// +// To reduce the complexity of this feature, it is implemented almost entirely +// in its own class, FunctionSplitter. The main inlining logic just calls out to +// the splitter to check if a function is worth splitting, and to get the split +// part if so. +// + +struct FunctionSplitter { + Module* module; + PassOptions& options; + + FunctionSplitter(Module* module, PassOptions& options) + : module(module), options(options) {} + + // Check if an function could be split in order to at least inline part of it, + // in a worthwhile manner. + // + // Even if this returns true, we may not end up inlining the function, as the + // main inlining logic has a few other considerations to take into account + // (like limitations on which functions can be inlined into in each iteration, + // the number of iterations, etc.). Therefore this function will only find out + // if we *can* split, but not actually do any splitting. + bool canSplit(Function* func) { + if (!canHandleParams(func)) { + return false; + } + + return maybeSplit(func); + } + + // Returns the function we should inline, after we split the function into two + // pieces as described above (that is, in the example above, this would return + // foo$inlineable). + // + // This is called when we are definitely inlining the function, and so it will + // perform the splitting (if that has not already been done before). + Function* getInlineableSplitFunction(Function* func) { + Function* inlineable = nullptr; + auto success = maybeSplit(func, &inlineable); + assert(success && inlineable); + return inlineable; + } + + // Clean up. When we are done we no longer need the inlineable functions on + // the module, as they have been inlined into all the places we wanted them + // for. + // + // Returns a list of the names of the functions we split. + std::vector<Name> finish() { + std::vector<Name> ret; + for (auto& kv : splits) { + Name func = kv.first; + auto& split = kv.second; + auto* inlineable = split.inlineable; + if (inlineable) { + module->removeFunction(inlineable->name); + ret.push_back(func); + } + } + return ret; + } + +private: + // Information about splitting a function. + struct Split { + // Whether we can split the function. If this is false, the other two will + // remain nullptr forever; if this is true then we will populate them the + // first time we need them. + bool splittable = false; + + // The inlineable function out of the two that we generate by splitting. + // That is, foo$inlineable from above. + Function* inlineable = nullptr; + + // The outlined function, that is, foo$outlined from above. + Function* outlined = nullptr; + }; + + // All the splitting we have already performed. + // + // Note that this maps from function names, and not Function*, as the main + // inlining code can remove functions as it goes, but we can rely on names + // staying constant. + std::unordered_map<Name, Split> splits; + + // Check if we can split a function. Returns whether we can. If the out param + // is provided, also actually does the split, and returns the inlineable split + // function in that out param. + bool maybeSplit(Function* func, Function** inlineableOut = nullptr) { + // Check if we've processed this input before. + auto iter = splits.find(func->name); + if (iter != splits.end()) { + if (!iter->second.splittable) { + // We've seen before that this cannot be split. + return false; + } + // We can split this function. If we've already done so, return that + // cached result. + if (iter->second.inlineable) { + if (inlineableOut) { + *inlineableOut = iter->second.inlineable; + } + return true; + } + // Otherwise, we are splittable but have not performed the split yet; + // proceed to do so. + } + + // The default value of split.splittable is false, so if we fail we just + // need to return false from this function. If, on the other hand, we can + // split, then we will update this split info accordingly. + auto& split = splits[func->name]; + + auto* body = func->body; + + // If the body is a block, and we have breaks to that block, then we cannot + // outline any code - we can't outline a break without the break's target. + if (auto* block = body->dynCast<Block>()) { + if (BranchUtils::BranchSeeker::has(block, block->name)) { + return false; + } + } + + // All the patterns we look for right now start with an if at the very top + // of the function. + auto* iff = getIf(body); + if (!iff) { + return false; + } + + // If the condition is not very simple, the benefits of this optimization + // are not obvious. + if (!isSimple(iff->condition)) { + return false; + } + + Builder builder(*module); + + // Pattern A: Check if the function begins with + // + // if (simple) return; + // + // TODO: support a return value + if (!iff->ifFalse && func->getResults() == Type::none && + iff->ifTrue->is<Return>()) { + // The body must be a block, because if it were not then the function + // would be easily inlineable (just an if with a simple condition and a + // return), and we would not even attempt to do splitting. + assert(body->is<Block>()); + + split.splittable = true; + // If we were just checking, stop and report success. + if (!inlineableOut) { + return true; + } + + // Note that "A" in the name here identifies this as being a split from + // pattern A. The second pattern B will have B in the name. + split.inlineable = copyFunction(func, "inlineable-A"); + auto* outlined = copyFunction(func, "outlined-A"); + + // The inlineable function should only have the if, which will call the + // outlined function with a flipped condition. + auto* inlineableIf = getIf(split.inlineable->body); + inlineableIf->condition = + builder.makeUnary(EqZInt32, inlineableIf->condition); + inlineableIf->ifTrue = builder.makeCall( + outlined->name, getForwardedArgs(func, builder), Type::none); + split.inlineable->body = inlineableIf; + + // The outlined function no longer needs the initial if. + auto& outlinedList = outlined->body->cast<Block>()->list; + outlinedList.erase(outlinedList.begin()); + + *inlineableOut = split.inlineable; + return true; + } + + // Pattern B: Represents a function whose entire body looks like + // + // if (A_1) { + // ..heavy work.. + // } + // .. + // if (A_k) { + // ..heavy work.. + // } + // B; // an optional final value (which can be a return value) + // + // where there is a small number of such ifs with arguments A1..A_k, and + // A_1..A_k and B (if the final value B exists) are very simple. + // + // Also, each if body must either be unreachable, or it must have type none + // and have no returns. If it is unreachable, for example because it is a + // return, then we will just return a value in the inlineable function: + // + // if (A_i) { + // return outlined(..); + // } + // + // Or, if an if body has type none, then for now we assume that we do not + // need to return a value from there, which makes things simpler, and in + // that case we just do this, which continues onward in the function: + // + // if (A_i) { + // outlined(..); + // } + // + // TODO: handle a possible returned value in this case as well. + // + // Note that the if body type must be unreachable or none, as this is an if + // without an else. + + // Find the number of ifs. + // TODO: Investigate more values here. 4 appears useful on real-world code. + const Index MaxIfs = 4; + Index numIfs = 0; + while (getIf(body, numIfs) && numIfs <= MaxIfs) { + numIfs++; + } + if (numIfs == 0 || numIfs > MaxIfs) { + return false; + } + + // Look for a final item after the ifs. + auto* finalItem = getItem(body, numIfs); + + // The final item must be simple (or not exist, which is simple enough). + if (finalItem && !isSimple(finalItem)) { + return false; + } + + // There must be no other items after the optional final one. + if (finalItem && getItem(body, numIfs + 1)) { + return false; + } + // This has the general shape we seek. Check each if. + for (Index i = 0; i < numIfs; i++) { + auto* iff = getIf(body, i); + // The if must have a simple condition and no else arm. + if (!isSimple(iff->condition) || iff->ifFalse) { + return false; + } + if (iff->ifTrue->type == Type::none) { + // This must have no returns. + if (!FindAll<Return>(iff->ifTrue).list.empty()) { + return false; + } + } else { + // This is an if without an else, and so the type is either none of + // unreachable; + assert(iff->ifTrue->type == Type::unreachable); + } + } + + // Success, this matches the pattern. Exit if we were just checking. + split.splittable = true; + if (!inlineableOut) { + return true; + } + + split.inlineable = copyFunction(func, "inlineable-B"); + + // The inlineable function should only have the ifs, which will call the + // outlined heavy work. + for (Index i = 0; i < numIfs; i++) { + // For each if, create an outlined function with the body of that if, + // and call that from the if. + auto* inlineableIf = getIf(split.inlineable->body, i); + auto* outlined = copyFunction(func, "outlined-B"); + outlined->body = inlineableIf->ifTrue; + + // The outlined function either returns the same results as the original + // one, or nothing, depending on if a value is returned here. + auto valueReturned = + func->getResults() != Type::none && outlined->body->type != Type::none; + outlined->setResults(valueReturned ? func->getResults() : Type::none); + inlineableIf->ifTrue = builder.makeCall(outlined->name, + getForwardedArgs(func, builder), + outlined->getResults()); + if (valueReturned) { + inlineableIf->ifTrue = builder.makeReturn(inlineableIf->ifTrue); + } + } + + // We can just leave the final value at the end, if it exists. + + *inlineableOut = split.inlineable; + return true; + } + + Function* copyFunction(Function* func, std::string prefix) { + // TODO: We copy quite a lot more than we need here, and throw stuff out. + // It is simple to just copy the entire thing to get the params and + // results and all that, but we could be more efficient. + prefix = "byn-split-" + prefix; + return ModuleUtils::copyFunction( + func, + *module, + Names::getValidFunctionName(*module, prefix + '$' + func->name.str)); + } + + // Get the i-th item in a sequence of initial items in an expression. That is, + // if the item is a block, it may have several such items, and otherwise there + // is a single item, that item itself. This basically provides a simpler + // interface than checking if something is a block or not when there is just + // one item. + // + // Returns nullptr if there is no such item. + static Expression* getItem(Expression* curr, Index i = 0) { + if (auto* block = curr->dynCast<Block>()) { + auto& list = block->list; + if (i < list.size()) { + return list[i]; + } + } + if (i == 0) { + return curr; + } + return nullptr; + } + + // Get the i-th if in a sequence of initial ifs in an expression. If no such + // if exists, returns nullptr. + static If* getIf(Expression* curr, Index i = 0) { + auto* item = getItem(curr, i); + if (!item) { + return nullptr; + } + if (auto* iff = item->dynCast<If>()) { + return iff; + } + return nullptr; + } + + // Checks if an expression is very simple - something simple enough that we + // are willing to inline it in this optimization. This should basically take + // almost no cost at all to compute. + bool isSimple(Expression* curr) { + // For now, support local and global gets, and unary operations. + // TODO: Generalize? Use costs.h? + if (curr->type == Type::unreachable) { + return false; + } + if (curr->is<GlobalGet>() || curr->is<LocalGet>()) { + return true; + } + if (auto* unary = curr->dynCast<Unary>()) { + return isSimple(unary->value); + } + if (auto* is = curr->dynCast<RefIs>()) { + return isSimple(is->value); + } + return false; + } + + // Returns a list of local.gets, one for each of the parameters to the + // function. This forwards the arguments passed to the inlineable function to + // the outlined one. + std::vector<Expression*> getForwardedArgs(Function* func, Builder& builder) { + std::vector<Expression*> args; + for (Index i = 0; i < func->getNumParams(); i++) { + args.push_back(builder.makeLocalGet(i, func->getLocalType(i))); + } + return args; + } +}; + struct Inlining : public Pass { // This pass changes locals and parameters. // FIXME DWARF updating does not handle local changes yet. @@ -343,7 +801,15 @@ struct Inlining : public Pass { // the information for each function. recomputed in each iteraction NameInfoMap infos; - void run(PassRunner* runner, Module* module) override { + std::unique_ptr<FunctionSplitter> functionSplitter; + + PassRunner* runner = nullptr; + Module* module = nullptr; + + void run(PassRunner* runner_, Module* module_) override { + runner = runner_; + module = module_; + // No point to do more iterations than the number of functions, as it means // we are infinitely recursing (which should be very rare in practice, but // it is possible that a recursive call can look like it is worth inlining). @@ -361,10 +827,17 @@ struct Inlining : public Pass { // then like loop unrolling it loses its benefit quickly, so set a limit // here. // + // In addition to inlining into a function, we track how many times we do + // other potentially repetitive operations like splitting a function before + // inlining, as any such repetitive operation should be limited in how many + // times we perform it. (An exception is how many times we inlined a + // function, which we do not want to limit - it can be profitable to inline + // a call into a great many callsites, over many iterations.) + // // (Track names here, and not Function pointers, as we can remove functions // while inlining, and it may be confusing during debugging to have a // pointer to something that was removed.) - std::unordered_map<Name, Index> iterationsInlinedInto; + std::unordered_map<Name, Index> iterationCounts; const size_t MaxIterationsForFunc = 5; @@ -373,12 +846,13 @@ struct Inlining : public Pass { std::cout << "inlining loop iter " << iterationNumber << " (numFunctions: " << module->functions.size() << ")\n"; #endif - - calculateInfos(module); - iterationNumber++; + std::unordered_set<Function*> inlinedInto; - iteration(runner, module, inlinedInto); + + prepare(); + iteration(inlinedInto); + if (inlinedInto.empty()) { return; } @@ -388,25 +862,35 @@ struct Inlining : public Pass { #endif for (auto* func : inlinedInto) { - if (++iterationsInlinedInto[func->name] >= MaxIterationsForFunc) { + if (++iterationCounts[func->name] >= MaxIterationsForFunc) { return; } } + + if (functionSplitter) { + auto splitNames = functionSplitter->finish(); + for (auto name : splitNames) { + if (++iterationCounts[name] >= MaxIterationsForFunc) { + return; + } + } + } } } - void calculateInfos(Module* module) { + void prepare() { infos.clear(); // fill in info, as we operate on it in parallel (each function to its own // entry) for (auto& func : module->functions) { infos[func->name]; } - PassRunner runner(module); - FunctionInfoScanner scanner(&infos); - scanner.run(&runner, module); - // fill in global uses - scanner.walkModuleCode(module); + { + PassRunner runner(module); + FunctionInfoScanner scanner(&infos); + scanner.run(&runner, module); + scanner.walkModuleCode(module); + } for (auto& ex : module->exports) { if (ex->kind == ExternalKind::Function) { infos[ex->value].usedGlobally = true; @@ -415,32 +899,42 @@ struct Inlining : public Pass { if (module->start.is()) { infos[module->start].usedGlobally = true; } + + // When optimizing heavily for size, we may potentially split functions in + // order to inline parts of them. + if (runner->options.optimizeLevel >= 3 && !runner->options.shrinkLevel) { + functionSplitter = + std::make_unique<FunctionSplitter>(module, runner->options); + } } - void iteration(PassRunner* runner, - Module* module, - std::unordered_set<Function*>& inlinedInto) { + void iteration(std::unordered_set<Function*>& inlinedInto) { // decide which to inline InliningState state; ModuleUtils::iterDefinedFunctions(*module, [&](Function* func) { - if (infos[func->name].worthInlining(runner->options)) { + if (worthInlining(func->name)) { state.worthInlining.insert(func->name); } }); if (state.worthInlining.size() == 0) { return; } - // fill in actionsForFunction, as we operate on it in parallel (each - // function to its own entry) + // Fill in actionsForFunction, as we operate on it in parallel (each + // function to its own entry). Also generate a vector of the function names + // so that in the later loop we can iterate on it deterministically and + // without iterator invalidation. + std::vector<Name> funcNames; for (auto& func : module->functions) { state.actionsForFunction[func->name]; + funcNames.push_back(func->name); } // find and plan inlinings Planner(&state).run(runner, module); // perform inlinings TODO: parallelize std::unordered_map<Name, Index> inlinedUses; // how many uses we inlined // which functions were inlined into - for (auto& func : module->functions) { + for (auto name : funcNames) { + auto* func = module->getFunction(name); // if we've inlined a function, don't inline into it in this iteration, // avoid risk of races // note that we do not risk stalling progress, as each iteration() will @@ -448,7 +942,7 @@ struct Inlining : public Pass { if (inlinedUses.count(func->name)) { continue; } - for (auto& action : state.actionsForFunction[func->name]) { + for (auto& action : state.actionsForFunction[name]) { auto* inlinedFunction = action.contents; // if we've inlined into a function, don't inline it in this iteration, // avoid risk of races @@ -461,12 +955,24 @@ struct Inlining : public Pass { if (!isUnderSizeLimit(func->name, inlinedName)) { continue; } + + // Success - we can inline. #ifdef INLINING_DEBUG std::cout << "inline " << inlinedName << " into " << func->name << '\n'; #endif - doInlining(module, func.get(), action); + + // Update the action for the actual inlining we are about to perform + // (when splitting, we will actually inline one of the split pieces and + // not the original function itself; note how even if we do that then + // we are still removing a call to the original function here, and so + // we do not need to change anything else lower down - we still want to + // note that we got rid of one use of the original function). + action.contents = getActuallyInlinedFunction(action.contents); + + // Perform the inlining and update counts. + doInlining(module, func, action); inlinedUses[inlinedName]++; - inlinedInto.insert(func.get()); + inlinedInto.insert(func); assert(inlinedUses[inlinedName] <= infos[inlinedName].refs); } } @@ -486,6 +992,41 @@ struct Inlining : public Pass { }); } + bool worthInlining(Name name) { + // Check if the function itself is worth inlining as it is. + if (infos[name].worthInlining(runner->options)) { + return true; + } + + // Otherwise, check if we can at least inline part of it, if we are + // interested in such things. + if (functionSplitter && + functionSplitter->canSplit(module->getFunction(name))) { + return true; + } + + return false; + } + + // Gets the actual function to be inlined. Normally this is the function + // itself, but if it is a function that we must first split (i.e., we only + // want to partially inline it) then it will be the inlineable part of the + // split. + // + // This is called right before actually performing the inlining, that is, we + // are guaranteed to inline after this. + Function* getActuallyInlinedFunction(Function* func) { + // If we want to inline this function itself, do so. + if (infos[func->name].worthInlining(runner->options)) { + return func; + } + + // Otherwise, this is a case where we want to inline part of it, after + // splitting. + assert(functionSplitter); + return functionSplitter->getInlineableSplitFunction(func); + } + // Checks if the combined size of the code after inlining is under the // absolute size limit. We have an absolute limit in order to avoid // extremely-large sizes after inlining, as they may hit limits in VMs and/or @@ -505,21 +1046,20 @@ struct Inlining : public Pass { } }; -Pass* createInliningPass() { return new Inlining(); } - -Pass* createInliningOptimizingPass() { - auto* ret = new Inlining(); - ret->optimize = true; - return ret; -} - -static const char* MAIN = "main"; -static const char* ORIGINAL_MAIN = "__original_main"; +} // anonymous namespace +// +// InlineMain +// // Inline __original_main into main, if they exist. This works around the odd // thing that clang/llvm currently do, where __original_main contains the user's // actual main (this is done as a workaround for main having two different // possible signatures). +// + +static const char* MAIN = "main"; +static const char* ORIGINAL_MAIN = "__original_main"; + struct InlineMainPass : public Pass { void run(PassRunner* runner, Module* module) override { auto* main = module->getFunctionOrNull(MAIN); @@ -547,6 +1087,14 @@ struct InlineMainPass : public Pass { } }; +Pass* createInliningPass() { return new Inlining(); } + +Pass* createInliningOptimizingPass() { + auto* ret = new Inlining(); + ret->optimize = true; + return ret; +} + Pass* createInlineMainPass() { return new InlineMainPass(); } } // namespace wasm diff --git a/test/lit/passes/inlining-optimizing_optimize-level=3.wast b/test/lit/passes/inlining-optimizing_optimize-level=3.wast index 4a4f21f94..47fe69553 100644 --- a/test/lit/passes/inlining-optimizing_optimize-level=3.wast +++ b/test/lit/passes/inlining-optimizing_optimize-level=3.wast @@ -25,12 +25,12 @@ (type $FUNCSIG$i (func (result i32))) (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$vii (func (param i32 i32))) + ;; CHECK: (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) + ;; CHECK: (type $i32_i32_i32_i32_i32_=>_i32 (func (param i32 i32 i32 i32 i32) (result i32))) ;; CHECK: (type $f64_i32_=>_f64 (func (param f64 i32) (result f64))) - ;; CHECK: (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) - ;; CHECK: (type $i32_i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32 i32))) ;; CHECK: (import "env" "memory" (memory $0 256 256)) @@ -4065,8 +4065,8 @@ ;; CHECK-NEXT: (local $21 i32) ;; CHECK-NEXT: (local $22 i32) ;; CHECK-NEXT: (local $23 i32) - ;; CHECK-NEXT: (local $24 f64) - ;; CHECK-NEXT: (local $25 i32) + ;; CHECK-NEXT: (local $24 i32) + ;; CHECK-NEXT: (local $25 f64) ;; CHECK-NEXT: (local $26 i32) ;; CHECK-NEXT: (local $27 i32) ;; CHECK-NEXT: (local $28 i32) @@ -4108,26 +4108,26 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $abort) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $21 + ;; CHECK-NEXT: (local.set $22 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.get $13) ;; CHECK-NEXT: (i32.const 16) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $33 + ;; CHECK-NEXT: (local.set $34 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.get $13) ;; CHECK-NEXT: (i32.const 528) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $28 + ;; CHECK-NEXT: (local.set $29 ;; CHECK-NEXT: (i32.ne ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $37 - ;; CHECK-NEXT: (local.tee $25 + ;; CHECK-NEXT: (local.tee $23 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.tee $5 ;; CHECK-NEXT: (i32.add @@ -4156,7 +4156,7 @@ ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $22 + ;; CHECK-NEXT: (local.set $20 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.tee $5 ;; CHECK-NEXT: (i32.add @@ -4175,9 +4175,9 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $43 ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: (local.tee $34 - ;; CHECK-NEXT: (local.tee $23 + ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.tee $35 + ;; CHECK-NEXT: (local.tee $24 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.get $13) ;; CHECK-NEXT: (i32.const 588) @@ -4189,12 +4189,12 @@ ;; CHECK-NEXT: (local.set $44 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (i32.const -2) - ;; CHECK-NEXT: (local.get $34) + ;; CHECK-NEXT: (local.get $35) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $45 ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $22) + ;; CHECK-NEXT: (local.get $20) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -4210,16 +4210,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $41 - ;; CHECK-NEXT: (local.tee $29 + ;; CHECK-NEXT: (local.tee $26 ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $23) + ;; CHECK-NEXT: (local.get $24) ;; CHECK-NEXT: (i32.const 9) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $32 + ;; CHECK-NEXT: (local.set $33 ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $23) + ;; CHECK-NEXT: (local.get $24) ;; CHECK-NEXT: (i32.const 8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -4352,7 +4352,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $28) + ;; CHECK-NEXT: (local.get $29) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (i32.and @@ -4386,7 +4386,7 @@ ;; CHECK-NEXT: (br $label$continue$L1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 + ;; CHECK-NEXT: (local.set $10 ;; CHECK-NEXT: (if (result i32) ;; CHECK-NEXT: (i32.lt_u ;; CHECK-NEXT: (local.tee $8 @@ -4428,7 +4428,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $19 + ;; CHECK-NEXT: (local.set $17 ;; CHECK-NEXT: (select ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: (i32.const -1) @@ -4445,7 +4445,7 @@ ;; CHECK-NEXT: (local.set $6 ;; CHECK-NEXT: (local.get $9) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $19 + ;; CHECK-NEXT: (local.set $17 ;; CHECK-NEXT: (i32.const -1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $1) @@ -4619,7 +4619,7 @@ ;; CHECK-NEXT: (local.set $8 ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 + ;; CHECK-NEXT: (local.set $16 ;; CHECK-NEXT: (i32.load ;; CHECK-NEXT: (local.get $6) ;; CHECK-NEXT: ) @@ -4632,7 +4632,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $8) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.set $18 ;; CHECK-NEXT: (i32.const -1) @@ -4642,7 +4642,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $28) + ;; CHECK-NEXT: (local.get $29) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.set $9 @@ -4651,7 +4651,7 @@ ;; CHECK-NEXT: (local.set $11 ;; CHECK-NEXT: (local.get $6) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 + ;; CHECK-NEXT: (local.set $16 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $do-once5 @@ -4659,7 +4659,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 + ;; CHECK-NEXT: (local.set $16 ;; CHECK-NEXT: (i32.load ;; CHECK-NEXT: (local.tee $11 ;; CHECK-NEXT: (i32.and @@ -4690,14 +4690,14 @@ ;; CHECK-NEXT: (local.set $9 ;; CHECK-NEXT: (if (result i32) ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $17 + ;; CHECK-NEXT: (local.set $16 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.or @@ -4742,7 +4742,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.tee $10 + ;; CHECK-NEXT: (local.tee $8 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (i32.load8_s ;; CHECK-NEXT: (local.tee $11 @@ -4762,7 +4762,7 @@ ;; CHECK-NEXT: (local.get $6) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $while-in8) ;; CHECK-NEXT: ) @@ -4783,10 +4783,10 @@ ;; CHECK-NEXT: (local.set $9 ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 + ;; CHECK-NEXT: (local.set $16 ;; CHECK-NEXT: (local.get $6) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -4794,10 +4794,10 @@ ;; CHECK-NEXT: (local.set $9 ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $17 + ;; CHECK-NEXT: (local.set $16 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -4967,7 +4967,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $28) + ;; CHECK-NEXT: (local.get $29) ;; CHECK-NEXT: (block (result i32) ;; CHECK-NEXT: (local.set $8 ;; CHECK-NEXT: (i32.load @@ -5010,13 +5010,13 @@ ;; CHECK-NEXT: (local.set $8 ;; CHECK-NEXT: (local.get $11) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $while-in13 ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.tee $12 + ;; CHECK-NEXT: (local.tee $10 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (i32.load8_s ;; CHECK-NEXT: (local.get $8) @@ -5042,19 +5042,19 @@ ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.lt_u ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.tee $12 + ;; CHECK-NEXT: (local.tee $10 ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (local.tee $15 ;; CHECK-NEXT: (i32.load8_s ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (i32.const 58) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 3611) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -5069,8 +5069,8 @@ ;; CHECK-NEXT: (local.set $8 ;; CHECK-NEXT: (local.get $11) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $while-in13) ;; CHECK-NEXT: ) @@ -5090,9 +5090,9 @@ ;; CHECK-NEXT: (br $label$break$L1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 + ;; CHECK-NEXT: (local.set $19 ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $19) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: (i32.const -1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -5107,7 +5107,7 @@ ;; CHECK-NEXT: (i32.const 19) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.set $18 ;; CHECK-NEXT: (i32.const -1) @@ -5118,25 +5118,25 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (i32.store ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.get $4) ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $19) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $15 ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.tee $12 + ;; CHECK-NEXT: (local.tee $10 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.get $3) ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $19) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -5146,7 +5146,7 @@ ;; CHECK-NEXT: (i32.store ;; CHECK-NEXT: (local.get $13) ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store offset=4 @@ -5158,7 +5158,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $28) + ;; CHECK-NEXT: (local.get $29) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.set $18 @@ -5169,7 +5169,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $_pop_arg_336 ;; CHECK-NEXT: (local.get $13) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: (local.get $2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -5178,7 +5178,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $28) + ;; CHECK-NEXT: (local.get $29) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.set $5 @@ -5193,7 +5193,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $9 ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.tee $12 + ;; CHECK-NEXT: (local.tee $10 ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (local.get $9) ;; CHECK-NEXT: (i32.const -65537) @@ -5213,7 +5213,7 @@ ;; CHECK-NEXT: (select ;; CHECK-NEXT: (local.tee $5 ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.tee $12 + ;; CHECK-NEXT: (local.tee $10 ;; CHECK-NEXT: (select ;; CHECK-NEXT: (local.tee $15 ;; CHECK-NEXT: (i32.sub @@ -5222,7 +5222,7 @@ ;; CHECK-NEXT: (call $_pad ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (local.tee $7 ;; CHECK-NEXT: (block $__rjti$7 (result i32) ;; CHECK-NEXT: (block $__rjti$6 @@ -5264,7 +5264,7 @@ ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -5283,7 +5283,7 @@ ;; CHECK-NEXT: (block $switch-case20 ;; CHECK-NEXT: (block $switch-case19 ;; CHECK-NEXT: (br_table $switch-case19 $switch-case20 $switch-case21 $switch-case22 $switch-case23 $switch-default26 $switch-case24 $switch-case25 $switch-default26 - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store @@ -5463,7 +5463,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $25) + ;; CHECK-NEXT: (local.get $23) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $while-in32 ;; CHECK-NEXT: (i32.store8 @@ -5498,7 +5498,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $25) + ;; CHECK-NEXT: (local.get $23) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if @@ -5506,32 +5506,27 @@ ;; CHECK-NEXT: (local.get $9) ;; CHECK-NEXT: (i32.const 8) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $37) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (local.set $6 + ;; CHECK-NEXT: (select + ;; CHECK-NEXT: (local.tee $5 + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (i32.sub + ;; CHECK-NEXT: (local.get $37) + ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $6) + ;; CHECK-NEXT: (i32.gt_s + ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $7 + ;; CHECK-NEXT: (local.get $9) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $5 ;; CHECK-NEXT: (local.get $8) @@ -5539,7 +5534,7 @@ ;; CHECK-NEXT: (local.set $8 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (i32.const 4091) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $__rjti$8) @@ -5589,13 +5584,13 @@ ;; CHECK-NEXT: (local.set $8 ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (i32.const 4091) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $__rjti$4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (if (result i32) ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (local.get $9) @@ -5639,7 +5634,7 @@ ;; CHECK-NEXT: (local.set $8 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (i32.const 4091) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $__rjti$4) @@ -5659,19 +5654,19 @@ ;; CHECK-NEXT: (local.get $38) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.set $10 ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $8 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (i32.const 4091) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $__rjto$8 - ;; CHECK-NEXT: (local.get $25) + ;; CHECK-NEXT: (local.get $23) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $5 @@ -5806,7 +5801,7 @@ ;; CHECK-NEXT: (call $_pad ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (local.get $9) ;; CHECK-NEXT: ) @@ -5822,7 +5817,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $21) + ;; CHECK-NEXT: (local.get $22) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (f64.store @@ -5910,11 +5905,11 @@ ;; CHECK-NEXT: (if ;; CHECK-NEXT: (local.tee $5 ;; CHECK-NEXT: (f64.ne - ;; CHECK-NEXT: (local.tee $24 + ;; CHECK-NEXT: (local.tee $25 ;; CHECK-NEXT: (f64.mul ;; CHECK-NEXT: (call $_frexp ;; CHECK-NEXT: (local.get $14) - ;; CHECK-NEXT: (local.get $21) + ;; CHECK-NEXT: (local.get $22) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (f64.const 2) ;; CHECK-NEXT: ) @@ -5923,10 +5918,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $21) + ;; CHECK-NEXT: (local.get $22) ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $21) + ;; CHECK-NEXT: (local.get $22) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) @@ -5934,7 +5929,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.tee $26 + ;; CHECK-NEXT: (local.tee $21 ;; CHECK-NEXT: (i32.or ;; CHECK-NEXT: (local.get $15) ;; CHECK-NEXT: (i32.const 32) @@ -5950,7 +5945,7 @@ ;; CHECK-NEXT: (i32.const 9) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $30) - ;; CHECK-NEXT: (local.tee $16 + ;; CHECK-NEXT: (local.tee $19 ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (local.get $15) ;; CHECK-NEXT: (i32.const 32) @@ -5974,7 +5969,7 @@ ;; CHECK-NEXT: (i32.const 11) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $24) + ;; CHECK-NEXT: (local.get $25) ;; CHECK-NEXT: (block (result f64) ;; CHECK-NEXT: (local.set $14 ;; CHECK-NEXT: (f64.const 8) @@ -6001,7 +5996,7 @@ ;; CHECK-NEXT: (local.get $14) ;; CHECK-NEXT: (f64.sub ;; CHECK-NEXT: (f64.neg - ;; CHECK-NEXT: (local.get $24) + ;; CHECK-NEXT: (local.get $25) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $14) ;; CHECK-NEXT: ) @@ -6009,7 +6004,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (f64.sub ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $24) + ;; CHECK-NEXT: (local.get $25) ;; CHECK-NEXT: (local.get $14) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $14) @@ -6031,40 +6026,59 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (call $_fmt_u - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (local.set $5 + ;; CHECK-NEXT: (local.tee $8 + ;; CHECK-NEXT: (select + ;; CHECK-NEXT: (i32.sub + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (local.tee $7 + ;; CHECK-NEXT: (i32.load + ;; CHECK-NEXT: (local.get $22) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $7) + ;; CHECK-NEXT: (i32.lt_s ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.tee $8 ;; CHECK-NEXT: (i32.shr_s ;; CHECK-NEXT: (i32.shl ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $5) + ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 31) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 31) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $22) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-B$_fmt_u + ;; CHECK-NEXT: (local.get $5) + ;; CHECK-NEXT: (local.get $8) + ;; CHECK-NEXT: (local.get $20) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $22) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $5) + ;; CHECK-NEXT: (call $byn-split-outlined-B$_fmt_u_0 + ;; CHECK-NEXT: (local.get $5) + ;; CHECK-NEXT: (local.get $8) + ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (local.tee $5 + ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (i32.store8 @@ -6110,7 +6124,7 @@ ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $20 + ;; CHECK-NEXT: (local.set $17 ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (local.get $9) @@ -6119,7 +6133,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $23) + ;; CHECK-NEXT: (local.get $24) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $while-in56 ;; CHECK-NEXT: (i32.store8 @@ -6156,7 +6170,7 @@ ;; CHECK-NEXT: (i32.const 4075) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $14 @@ -6180,13 +6194,13 @@ ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $34) + ;; CHECK-NEXT: (local.get $35) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if (result i32) ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (local.get $15) ;; CHECK-NEXT: (f64.eq @@ -6220,7 +6234,7 @@ ;; CHECK-NEXT: (call $_pad ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (local.tee $7 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.tee $6 @@ -6279,7 +6293,7 @@ ;; CHECK-NEXT: (call $_pad ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (i32.xor ;; CHECK-NEXT: (local.get $9) @@ -6289,7 +6303,7 @@ ;; CHECK-NEXT: (local.set $5 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $34) + ;; CHECK-NEXT: (local.get $35) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if @@ -6303,7 +6317,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $23) + ;; CHECK-NEXT: (local.get $24) ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -6318,7 +6332,7 @@ ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: (local.tee $6 ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $22) + ;; CHECK-NEXT: (local.get $20) ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6347,7 +6361,7 @@ ;; CHECK-NEXT: (call $_pad ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (i32.xor ;; CHECK-NEXT: (local.get $9) @@ -6356,11 +6370,11 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $do-once49 ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (i32.lt_s ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6371,28 +6385,28 @@ ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: (block (result f64) ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $21) + ;; CHECK-NEXT: (local.get $22) ;; CHECK-NEXT: (local.tee $5 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $21) + ;; CHECK-NEXT: (local.get $22) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 28) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (f64.mul - ;; CHECK-NEXT: (local.get $24) + ;; CHECK-NEXT: (local.get $25) ;; CHECK-NEXT: (f64.const 268435456) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result f64) ;; CHECK-NEXT: (local.set $5 ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $21) + ;; CHECK-NEXT: (local.get $22) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $24) + ;; CHECK-NEXT: (local.get $25) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6463,9 +6477,9 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.tee $10 + ;; CHECK-NEXT: (local.tee $12 ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $21) + ;; CHECK-NEXT: (local.get $22) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 0) @@ -6475,19 +6489,19 @@ ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $while-in62 - ;; CHECK-NEXT: (local.set $16 + ;; CHECK-NEXT: (local.set $19 ;; CHECK-NEXT: (select ;; CHECK-NEXT: (i32.const 29) - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (i32.const 29) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.tee $10 + ;; CHECK-NEXT: (local.tee $12 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (i32.const 4) @@ -6496,58 +6510,58 @@ ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block $do-once63 - ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.set $10 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $while-in66 ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (call $___uremdi3 ;; CHECK-NEXT: (block (result i32) ;; CHECK-NEXT: (global.set $tempRet0 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.tee $20 + ;; CHECK-NEXT: (local.tee $17 ;; CHECK-NEXT: (call $_bitshift64Shl ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $12 + ;; CHECK-NEXT: (local.tee $10 ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (global.get $tempRet0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $20 + ;; CHECK-NEXT: (local.tee $17 ;; CHECK-NEXT: (global.get $tempRet0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 1000000000) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.set $10 ;; CHECK-NEXT: (call $___udivdi3 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: (i32.const 1000000000) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $while-in66 ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.tee $10 + ;; CHECK-NEXT: (local.tee $12 ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6557,7 +6571,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $do-once63 ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store @@ -6567,7 +6581,7 @@ ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6598,19 +6612,19 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: (local.tee $10 + ;; CHECK-NEXT: (local.get $22) + ;; CHECK-NEXT: (local.tee $12 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $21) + ;; CHECK-NEXT: (local.get $22) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $while-in62 ;; CHECK-NEXT: (i32.gt_s - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6620,7 +6634,7 @@ ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $19 + ;; CHECK-NEXT: (local.set $17 ;; CHECK-NEXT: (select ;; CHECK-NEXT: (i32.const 6) ;; CHECK-NEXT: (local.get $6) @@ -6632,15 +6646,15 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $20 + ;; CHECK-NEXT: (local.set $19 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (i32.div_s ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $19) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: (i32.const 25) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 9) @@ -6648,9 +6662,9 @@ ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $31 + ;; CHECK-NEXT: (local.set $28 ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $26) + ;; CHECK-NEXT: (local.get $21) ;; CHECK-NEXT: (i32.const 102) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6662,13 +6676,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $5 ;; CHECK-NEXT: (loop $while-in70 (result i32) - ;; CHECK-NEXT: (local.set $16 + ;; CHECK-NEXT: (local.set $10 ;; CHECK-NEXT: (select ;; CHECK-NEXT: (i32.const 9) ;; CHECK-NEXT: (local.tee $7 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.gt_s @@ -6683,22 +6697,22 @@ ;; CHECK-NEXT: (local.get $6) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block $do-once71 - ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.set $31 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (i32.shl ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $35 + ;; CHECK-NEXT: (local.set $36 ;; CHECK-NEXT: (i32.shr_u ;; CHECK-NEXT: (i32.const 1000000000) - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $7 @@ -6708,24 +6722,24 @@ ;; CHECK-NEXT: (i32.store ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (i32.shr_u - ;; CHECK-NEXT: (local.tee $10 + ;; CHECK-NEXT: (local.tee $32 ;; CHECK-NEXT: (i32.load ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (i32.mul ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $31) + ;; CHECK-NEXT: (local.get $32) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $35) + ;; CHECK-NEXT: (local.get $36) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $while-in74 @@ -6754,12 +6768,12 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $do-once71 ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $5 ;; CHECK-NEXT: (i32.add @@ -6781,18 +6795,18 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.set $5 ;; CHECK-NEXT: (select ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.tee $6 ;; CHECK-NEXT: (select ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $31) + ;; CHECK-NEXT: (local.get $28) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6805,38 +6819,35 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store - ;; CHECK-NEXT: (local.get $21) - ;; CHECK-NEXT: (local.tee $10 + ;; CHECK-NEXT: (local.get $22) + ;; CHECK-NEXT: (local.tee $12 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $21) + ;; CHECK-NEXT: (local.get $22) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if (result i32) ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.set $6 ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $while-in70) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: ) @@ -6844,24 +6855,24 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $20 + ;; CHECK-NEXT: (local.set $19 ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.lt_u ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block $do-once75 ;; CHECK-NEXT: (local.set $7 ;; CHECK-NEXT: (i32.mul ;; CHECK-NEXT: (i32.shr_s ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 2) @@ -6912,12 +6923,12 @@ ;; CHECK-NEXT: (local.tee $6 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $19) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: (select ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $26) + ;; CHECK-NEXT: (local.get $21) ;; CHECK-NEXT: (i32.const 102) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6927,13 +6938,13 @@ ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (local.tee $31 ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.get $19) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $35 + ;; CHECK-NEXT: (local.tee $36 ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $26) + ;; CHECK-NEXT: (local.get $21) ;; CHECK-NEXT: (i32.const 103) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -6948,8 +6959,8 @@ ;; CHECK-NEXT: (i32.mul ;; CHECK-NEXT: (i32.shr_s ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) @@ -6984,13 +6995,13 @@ ;; CHECK-NEXT: (i32.const 9) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.set $10 ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $while-in80 - ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.set $10 ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -7007,17 +7018,17 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.set $10 ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (local.tee $8 + ;; CHECK-NEXT: (local.set $8 + ;; CHECK-NEXT: (local.tee $21 ;; CHECK-NEXT: (i32.load ;; CHECK-NEXT: (local.tee $6 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: (i32.shl ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: (i32.const 2) @@ -7029,40 +7040,39 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 - ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (local.get $16) - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $26 + ;; CHECK-NEXT: (local.tee $28 ;; CHECK-NEXT: (i32.eq ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.get $6) ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.tee $8 + ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (i32.rem_u + ;; CHECK-NEXT: (local.get $8) + ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block $do-once81 - ;; CHECK-NEXT: (local.set $36 + ;; CHECK-NEXT: (local.set $32 ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: (i32.div_u - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $21) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) @@ -7070,10 +7080,10 @@ ;; CHECK-NEXT: (local.set $14 ;; CHECK-NEXT: (if (result f64) ;; CHECK-NEXT: (i32.lt_u - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: (local.tee $48 ;; CHECK-NEXT: (i32.div_s - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -7083,21 +7093,21 @@ ;; CHECK-NEXT: (f64.const 1) ;; CHECK-NEXT: (f64.const 1.5) ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $26) + ;; CHECK-NEXT: (local.get $28) ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: (local.get $48) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $24 + ;; CHECK-NEXT: (local.set $25 ;; CHECK-NEXT: (select ;; CHECK-NEXT: (f64.const 9007199254740994) ;; CHECK-NEXT: (f64.const 9007199254740992) ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $36) + ;; CHECK-NEXT: (local.get $32) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -7112,9 +7122,9 @@ ;; CHECK-NEXT: (i32.const 45) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $24 + ;; CHECK-NEXT: (local.set $25 ;; CHECK-NEXT: (f64.neg - ;; CHECK-NEXT: (local.get $24) + ;; CHECK-NEXT: (local.get $25) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $14 @@ -7129,18 +7139,18 @@ ;; CHECK-NEXT: (local.get $6) ;; CHECK-NEXT: (local.tee $8 ;; CHECK-NEXT: (i32.sub + ;; CHECK-NEXT: (local.get $21) ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $do-once81 ;; CHECK-NEXT: (f64.eq ;; CHECK-NEXT: (f64.add - ;; CHECK-NEXT: (local.get $24) + ;; CHECK-NEXT: (local.get $25) ;; CHECK-NEXT: (local.get $14) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $24) + ;; CHECK-NEXT: (local.get $25) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store @@ -7148,7 +7158,7 @@ ;; CHECK-NEXT: (local.tee $7 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -7205,7 +7215,7 @@ ;; CHECK-NEXT: (i32.mul ;; CHECK-NEXT: (i32.shr_s ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 2) @@ -7223,7 +7233,7 @@ ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.set $10 ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $while-in88 @@ -7236,9 +7246,9 @@ ;; CHECK-NEXT: (br_if $while-in88 ;; CHECK-NEXT: (i32.ge_u ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.tee $12 + ;; CHECK-NEXT: (local.tee $10 ;; CHECK-NEXT: (i32.mul - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -7247,7 +7257,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.set $10 ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $8 @@ -7260,40 +7270,40 @@ ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (i32.lt_u ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.set $10 ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $8 ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $36 + ;; CHECK-NEXT: (local.set $32 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (loop $while-in90 (result i32) ;; CHECK-NEXT: (block $while-out89 (result i32) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.le_u ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $26 + ;; CHECK-NEXT: (local.set $28 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $while-out89 @@ -7311,7 +7321,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $26 + ;; CHECK-NEXT: (local.set $28 ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $5) @@ -7329,14 +7339,14 @@ ;; CHECK-NEXT: (call $_pad ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (local.tee $8 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.tee $5 ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.get $35) + ;; CHECK-NEXT: (local.get $36) ;; CHECK-NEXT: (block $do-once91 (result i32) ;; CHECK-NEXT: (local.set $7 ;; CHECK-NEXT: (if (result i32) @@ -7347,7 +7357,7 @@ ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (local.get $31) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $19) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $8) @@ -7358,7 +7368,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $19 + ;; CHECK-NEXT: (local.set $17 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (local.get $5) @@ -7373,7 +7383,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $19 + ;; CHECK-NEXT: (local.set $17 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: (i32.const 1) @@ -7388,8 +7398,8 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (br_if $do-once91 - ;; CHECK-NEXT: (local.get $19) - ;; CHECK-NEXT: (local.tee $16 + ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.tee $21 ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (local.get $9) ;; CHECK-NEXT: (i32.const 8) @@ -7398,14 +7408,14 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $26) + ;; CHECK-NEXT: (local.get $28) ;; CHECK-NEXT: (block $do-once93 ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (local.tee $15 ;; CHECK-NEXT: (i32.load ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -7448,7 +7458,7 @@ ;; CHECK-NEXT: (br_if $while-in96 ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (if (result i32) - ;; CHECK-NEXT: (local.tee $16 + ;; CHECK-NEXT: (local.tee $21 ;; CHECK-NEXT: (local.tee $6 ;; CHECK-NEXT: (i32.mul ;; CHECK-NEXT: (local.get $6) @@ -7458,7 +7468,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.rem_u ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $21) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) @@ -7475,8 +7485,8 @@ ;; CHECK-NEXT: (i32.mul ;; CHECK-NEXT: (i32.shr_s ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) @@ -7494,11 +7504,11 @@ ;; CHECK-NEXT: (i32.const 102) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $16 + ;; CHECK-NEXT: (local.set $21 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $19) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: (local.tee $5 ;; CHECK-NEXT: (select ;; CHECK-NEXT: (i32.const 0) @@ -7516,16 +7526,16 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.gt_s ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $19) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $16 + ;; CHECK-NEXT: (local.set $21 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $19) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: (local.tee $5 ;; CHECK-NEXT: (select ;; CHECK-NEXT: (i32.const 0) @@ -7546,14 +7556,14 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.gt_s ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $19) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $16 + ;; CHECK-NEXT: (local.set $21 ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (local.get $9) ;; CHECK-NEXT: (i32.const 8) @@ -7562,7 +7572,7 @@ ;; CHECK-NEXT: (local.set $7 ;; CHECK-NEXT: (local.get $15) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $19) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -7572,10 +7582,10 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $19 + ;; CHECK-NEXT: (local.tee $17 ;; CHECK-NEXT: (i32.or ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $21) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 0) @@ -7606,36 +7616,55 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $22) - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (call $_fmt_u - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $36) - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (local.set $6 + ;; CHECK-NEXT: (local.tee $15 + ;; CHECK-NEXT: (select + ;; CHECK-NEXT: (local.get $32) + ;; CHECK-NEXT: (local.get $8) + ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (local.get $8) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.shr_s - ;; CHECK-NEXT: (i32.shl - ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 31) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.tee $15 + ;; CHECK-NEXT: (i32.shr_s + ;; CHECK-NEXT: (i32.shl + ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (local.get $15) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 31) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $22) + ;; CHECK-NEXT: (i32.const 31) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-B$_fmt_u + ;; CHECK-NEXT: (local.get $6) + ;; CHECK-NEXT: (local.get $15) + ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $6) + ;; CHECK-NEXT: (call $byn-split-outlined-B$_fmt_u_0 + ;; CHECK-NEXT: (local.get $6) + ;; CHECK-NEXT: (local.get $15) + ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.lt_s + ;; CHECK-NEXT: (i32.sub + ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.tee $6 + ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $while-in98 ;; CHECK-NEXT: (i32.store8 @@ -7650,7 +7679,7 @@ ;; CHECK-NEXT: (br_if $while-in98 ;; CHECK-NEXT: (i32.lt_s ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $22) + ;; CHECK-NEXT: (local.get $20) ;; CHECK-NEXT: (local.get $6) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 2) @@ -7684,7 +7713,7 @@ ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $22) + ;; CHECK-NEXT: (local.get $20) ;; CHECK-NEXT: (local.get $15) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -7713,7 +7742,7 @@ ;; CHECK-NEXT: (call $_pad ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: (i32.xor ;; CHECK-NEXT: (local.get $9) @@ -7724,53 +7753,59 @@ ;; CHECK-NEXT: (local.get $31) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.tee $12 + ;; CHECK-NEXT: (local.tee $10 ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $20) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $19) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $12) - ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $while-in102 - ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (call $_fmt_u + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.tee $7 ;; CHECK-NEXT: (i32.load ;; CHECK-NEXT: (local.get $6) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-B$_fmt_u_0 + ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $29) + ;; CHECK-NEXT: (local.get $26) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $7 + ;; CHECK-NEXT: (local.get $26) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block $do-once103 ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eq ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (br_if $do-once103 ;; CHECK-NEXT: (i32.ne ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $29) + ;; CHECK-NEXT: (local.get $26) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $32) + ;; CHECK-NEXT: (local.get $33) ;; CHECK-NEXT: (i32.const 48) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $32) + ;; CHECK-NEXT: (local.get $33) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (br_if $do-once103 ;; CHECK-NEXT: (i32.le_u ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $23) + ;; CHECK-NEXT: (local.get $24) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $while-in106 @@ -7786,7 +7821,7 @@ ;; CHECK-NEXT: (br_if $while-in106 ;; CHECK-NEXT: (i32.gt_u ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $23) + ;; CHECK-NEXT: (local.get $24) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -7821,7 +7856,7 @@ ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.set $6 @@ -7832,7 +7867,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $19) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (i32.and @@ -7859,7 +7894,7 @@ ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (i32.lt_u ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.gt_s ;; CHECK-NEXT: (local.get $5) @@ -7868,17 +7903,25 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $while-in110 (result i32) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.tee $6 - ;; CHECK-NEXT: (call $_fmt_u + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.tee $6 ;; CHECK-NEXT: (i32.load ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-B$_fmt_u_0 + ;; CHECK-NEXT: (local.get $6) ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $29) + ;; CHECK-NEXT: (local.get $26) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $23) + ;; CHECK-NEXT: (i32.gt_u + ;; CHECK-NEXT: (local.tee $6 + ;; CHECK-NEXT: (local.get $26) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $24) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $while-in112 ;; CHECK-NEXT: (i32.store8 @@ -7893,7 +7936,7 @@ ;; CHECK-NEXT: (br_if $while-in112 ;; CHECK-NEXT: (i32.gt_u ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $23) + ;; CHECK-NEXT: (local.get $24) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -7937,7 +7980,7 @@ ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.gt_s ;; CHECK-NEXT: (local.get $5) @@ -7962,14 +8005,14 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block $do-once99 - ;; CHECK-NEXT: (local.set $20 + ;; CHECK-NEXT: (local.set $19 ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $26) + ;; CHECK-NEXT: (local.get $28) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call $_pad @@ -7982,38 +8025,46 @@ ;; CHECK-NEXT: (i32.const -1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $16 + ;; CHECK-NEXT: (local.set $17 ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $21) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $6 - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $7 ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $while-in114 (result i32) ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.eq - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (call $_fmt_u + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.tee $5 ;; CHECK-NEXT: (i32.load ;; CHECK-NEXT: (local.get $6) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-B$_fmt_u_0 + ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: (local.get $29) + ;; CHECK-NEXT: (local.get $26) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.eq + ;; CHECK-NEXT: (local.tee $5 + ;; CHECK-NEXT: (local.get $26) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $26) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $29) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.get $32) + ;; CHECK-NEXT: (local.get $33) ;; CHECK-NEXT: (i32.const 48) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $32) + ;; CHECK-NEXT: (local.get $33) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -8021,7 +8072,7 @@ ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eq ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (if @@ -8049,7 +8100,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $do-once115 ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $17) ;; CHECK-NEXT: (i32.lt_s ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (i32.const 1) @@ -8076,7 +8127,7 @@ ;; CHECK-NEXT: (br_if $do-once115 ;; CHECK-NEXT: (i32.le_u ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $23) + ;; CHECK-NEXT: (local.get $24) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $while-in118 @@ -8092,14 +8143,14 @@ ;; CHECK-NEXT: (br_if $while-in118 ;; CHECK-NEXT: (i32.gt_u ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $23) + ;; CHECK-NEXT: (local.get $24) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (local.get $41) ;; CHECK-NEXT: (local.get $5) @@ -8118,11 +8169,11 @@ ;; CHECK-NEXT: (call $___fwritex ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (i32.gt_s ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $0) @@ -8138,13 +8189,13 @@ ;; CHECK-NEXT: (i32.const 4) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $20) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.gt_s ;; CHECK-NEXT: (local.tee $7 ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const -1) @@ -8173,7 +8224,7 @@ ;; CHECK-NEXT: (call $___fwritex ;; CHECK-NEXT: (local.get $15) ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $22) + ;; CHECK-NEXT: (local.get $20) ;; CHECK-NEXT: (local.get $15) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $0) @@ -8184,7 +8235,7 @@ ;; CHECK-NEXT: (call $_pad ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: (i32.xor ;; CHECK-NEXT: (local.get $9) @@ -8192,11 +8243,11 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: (i32.lt_s ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -8204,7 +8255,7 @@ ;; CHECK-NEXT: (call $_pad ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (local.tee $7 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.tee $8 @@ -8222,7 +8273,7 @@ ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.eqz @@ -8291,7 +8342,7 @@ ;; CHECK-NEXT: (call $_pad ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (i32.xor ;; CHECK-NEXT: (local.get $9) @@ -8299,11 +8350,11 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (i32.lt_s ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -8320,17 +8371,17 @@ ;; CHECK-NEXT: (local.set $7 ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.set $10 ;; CHECK-NEXT: (local.get $6) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $8 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (i32.const 4091) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $__rjto$8 - ;; CHECK-NEXT: (local.get $25) + ;; CHECK-NEXT: (local.get $23) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $10 @@ -8339,63 +8390,63 @@ ;; CHECK-NEXT: (i32.const 32) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (i32.load - ;; CHECK-NEXT: (local.get $13) + ;; CHECK-NEXT: (local.set $8 + ;; CHECK-NEXT: (if (result i32) + ;; CHECK-NEXT: (i32.or + ;; CHECK-NEXT: (local.tee $5 + ;; CHECK-NEXT: (i32.load + ;; CHECK-NEXT: (local.get $13) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.load offset=4 - ;; CHECK-NEXT: (local.get $13) + ;; CHECK-NEXT: (local.tee $9 + ;; CHECK-NEXT: (i32.load offset=4 + ;; CHECK-NEXT: (local.get $13) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (loop $while-in123 (result i32) - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (local.set $8 + ;; CHECK-NEXT: (local.get $23) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $5 + ;; CHECK-NEXT: (loop $while-in123 (result i32) + ;; CHECK-NEXT: (i32.store8 + ;; CHECK-NEXT: (local.tee $8 + ;; CHECK-NEXT: (i32.sub + ;; CHECK-NEXT: (local.get $8) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (i32.const 15) + ;; CHECK-NEXT: (i32.or + ;; CHECK-NEXT: (i32.load8_u + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (local.get $5) + ;; CHECK-NEXT: (i32.const 15) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 4075) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 4075) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in123 - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (local.tee $5 - ;; CHECK-NEXT: (call $_bitshift64Lshr - ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: (i32.const 4) + ;; CHECK-NEXT: (br_if $while-in123 + ;; CHECK-NEXT: (i32.or + ;; CHECK-NEXT: (local.tee $5 + ;; CHECK-NEXT: (call $_bitshift64Lshr + ;; CHECK-NEXT: (local.get $5) + ;; CHECK-NEXT: (local.get $9) + ;; CHECK-NEXT: (i32.const 4) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.tee $9 + ;; CHECK-NEXT: (global.get $tempRet0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (global.get $tempRet0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 ;; CHECK-NEXT: (if (result i32) ;; CHECK-NEXT: (i32.or ;; CHECK-NEXT: (i32.eqz @@ -8416,13 +8467,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (i32.const 4091) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (i32.shr_s ;; CHECK-NEXT: (local.get $15) @@ -8435,28 +8486,38 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (local.get $25) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $8 + ;; CHECK-NEXT: (block (result i32) + ;; CHECK-NEXT: (local.set $5 + ;; CHECK-NEXT: (local.get $23) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (i32.const 4091) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 - ;; CHECK-NEXT: (i32.const 4091) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $__rjti$8) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $5 - ;; CHECK-NEXT: (call $_fmt_u + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $7) + ;; CHECK-NEXT: (call $byn-split-outlined-B$_fmt_u + ;; CHECK-NEXT: (local.get $5) + ;; CHECK-NEXT: (local.get $7) + ;; CHECK-NEXT: (local.get $23) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $5) + ;; CHECK-NEXT: (call $byn-split-outlined-B$_fmt_u_0 ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $25) + ;; CHECK-NEXT: (local.get $23) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $5 + ;; CHECK-NEXT: (local.get $23) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $7 ;; CHECK-NEXT: (local.get $9) ;; CHECK-NEXT: ) @@ -8466,7 +8527,7 @@ ;; CHECK-NEXT: (block $__rjti$29 ;; CHECK-NEXT: (if ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $10 + ;; CHECK-NEXT: (local.tee $9 ;; CHECK-NEXT: (i32.ne ;; CHECK-NEXT: (local.tee $7 ;; CHECK-NEXT: (local.get $6) @@ -8476,7 +8537,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.ne ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $9 + ;; CHECK-NEXT: (local.tee $8 ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 3) @@ -8484,55 +8545,42 @@ ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (loop $while-in12 - ;; CHECK-NEXT: (br_if $__rjti$29 - ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (i32.load8_u - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (loop $while-in12 + ;; CHECK-NEXT: (br_if $__rjti$29 + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (i32.load8_u + ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br_if $while-in12 - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $9 - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (local.tee $7 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br_if $while-in12 + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (local.tee $9 + ;; CHECK-NEXT: (i32.ne + ;; CHECK-NEXT: (local.tee $7 + ;; CHECK-NEXT: (i32.sub + ;; CHECK-NEXT: (local.get $7) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.ne - ;; CHECK-NEXT: (i32.and - ;; CHECK-NEXT: (local.tee $8 - ;; CHECK-NEXT: (i32.add - ;; CHECK-NEXT: (local.get $8) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.ne + ;; CHECK-NEXT: (i32.and + ;; CHECK-NEXT: (local.tee $8 + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (local.get $8) + ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 3) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $8 - ;; CHECK-NEXT: (local.get $9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br_if $__rjti$29 ;; CHECK-NEXT: (local.get $9) @@ -8644,7 +8692,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $16 + ;; CHECK-NEXT: (local.set $19 ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (local.tee $15 ;; CHECK-NEXT: (select @@ -8656,9 +8704,9 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $9 - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.set $10 ;; CHECK-NEXT: (select ;; CHECK-NEXT: (local.get $6) ;; CHECK-NEXT: (i32.sub @@ -8667,13 +8715,13 @@ ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $8 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $10 + ;; CHECK-NEXT: (local.set $12 ;; CHECK-NEXT: (i32.const 4091) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $__rjto$8 @@ -8683,7 +8731,7 @@ ;; CHECK-NEXT: (local.get $6) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $15) - ;; CHECK-NEXT: (local.get $16) + ;; CHECK-NEXT: (local.get $19) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -8714,7 +8762,7 @@ ;; CHECK-NEXT: (i32.lt_s ;; CHECK-NEXT: (local.tee $7 ;; CHECK-NEXT: (call $_wctomb - ;; CHECK-NEXT: (local.get $33) + ;; CHECK-NEXT: (local.get $34) ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -8763,7 +8811,7 @@ ;; CHECK-NEXT: (call $_pad ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const 32) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (local.get $5) ;; CHECK-NEXT: (local.get $9) ;; CHECK-NEXT: ) @@ -8799,7 +8847,7 @@ ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (local.tee $8 ;; CHECK-NEXT: (call $_wctomb - ;; CHECK-NEXT: (local.get $33) + ;; CHECK-NEXT: (local.get $34) ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -8821,7 +8869,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $33) + ;; CHECK-NEXT: (local.get $34) ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -8856,11 +8904,11 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $11 ;; CHECK-NEXT: (select - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: (i32.lt_s ;; CHECK-NEXT: (local.get $7) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -8879,11 +8927,11 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $12 + ;; CHECK-NEXT: (local.set $10 ;; CHECK-NEXT: (if (result i32) ;; CHECK-NEXT: (i32.or ;; CHECK-NEXT: (local.get $6) - ;; CHECK-NEXT: (local.tee $12 + ;; CHECK-NEXT: (local.tee $7 ;; CHECK-NEXT: (i32.or ;; CHECK-NEXT: (i32.ne ;; CHECK-NEXT: (i32.load @@ -8905,7 +8953,7 @@ ;; CHECK-NEXT: (local.tee $5 ;; CHECK-NEXT: (i32.add ;; CHECK-NEXT: (i32.eqz - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.sub ;; CHECK-NEXT: (local.get $37) @@ -8922,20 +8970,20 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) ;; CHECK-NEXT: (local.set $7 - ;; CHECK-NEXT: (local.get $25) + ;; CHECK-NEXT: (local.get $23) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $25) + ;; CHECK-NEXT: (local.get $23) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $7) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: (i32.lt_s - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: (local.get $15) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -8943,10 +8991,10 @@ ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: (i32.gt_s ;; CHECK-NEXT: (local.get $5) - ;; CHECK-NEXT: (local.get $17) + ;; CHECK-NEXT: (local.get $16) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -8964,7 +9012,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (call $___fwritex - ;; CHECK-NEXT: (local.get $10) + ;; CHECK-NEXT: (local.get $12) ;; CHECK-NEXT: (local.get $8) ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: ) @@ -8983,7 +9031,7 @@ ;; CHECK-NEXT: (call $_pad ;; CHECK-NEXT: (local.get $0) ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: (local.get $12) + ;; CHECK-NEXT: (local.get $10) ;; CHECK-NEXT: (local.get $15) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) @@ -14846,93 +14894,6 @@ ) ) ) - ;; CHECK: (func $_fmt_u (param $0 i32) (param $1 i32) (param $2 i32) (result i32) - ;; CHECK-NEXT: (local $3 i32) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (loop $while-in - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (call $___uremdi3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (call $___udivdi3 - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: (i32.const 0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $3 - ;; CHECK-NEXT: (global.get $tempRet0) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.gt_u - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: (i32.const 9) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (local.get $3) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (loop $while-in1 - ;; CHECK-NEXT: (i32.store8 - ;; CHECK-NEXT: (local.tee $2 - ;; CHECK-NEXT: (i32.sub - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: (i32.const 1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.or - ;; CHECK-NEXT: (i32.rem_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (i32.const 48) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.set $1 - ;; CHECK-NEXT: (i32.div_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (if - ;; CHECK-NEXT: (i32.ge_u - ;; CHECK-NEXT: (local.get $0) - ;; CHECK-NEXT: (i32.const 10) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block - ;; CHECK-NEXT: (local.set $0 - ;; CHECK-NEXT: (local.get $1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (br $while-in1) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (local.get $2) - ;; CHECK-NEXT: ) (func $_fmt_u (param $0 i32) (param $1 i32) (param $2 i32) (result i32) (local $3 i32) (local $4 i32) @@ -31060,3 +31021,87 @@ ) ) ) +;; CHECK: (func $byn-split-outlined-B$_fmt_u (param $0 i32) (param $1 i32) (param $2 i32) +;; CHECK-NEXT: (local $3 i32) +;; CHECK-NEXT: (loop $while-in +;; CHECK-NEXT: (i32.store8 +;; CHECK-NEXT: (local.tee $2 +;; CHECK-NEXT: (i32.sub +;; CHECK-NEXT: (local.get $2) +;; CHECK-NEXT: (i32.const 1) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (i32.or +;; CHECK-NEXT: (call $___uremdi3 +;; CHECK-NEXT: (local.get $0) +;; CHECK-NEXT: (local.get $1) +;; CHECK-NEXT: (i32.const 10) +;; CHECK-NEXT: (i32.const 0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (i32.const 48) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (local.set $0 +;; CHECK-NEXT: (call $___udivdi3 +;; CHECK-NEXT: (local.get $0) +;; CHECK-NEXT: (local.get $1) +;; CHECK-NEXT: (i32.const 10) +;; CHECK-NEXT: (i32.const 0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (local.set $3 +;; CHECK-NEXT: (global.get $tempRet0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (if +;; CHECK-NEXT: (i32.gt_u +;; CHECK-NEXT: (local.get $1) +;; CHECK-NEXT: (i32.const 9) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (block +;; CHECK-NEXT: (local.set $1 +;; CHECK-NEXT: (local.get $3) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (br $while-in) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + +;; CHECK: (func $byn-split-outlined-B$_fmt_u_0 (param $0 i32) (param $1 i32) (param $2 i32) +;; CHECK-NEXT: (local $3 i32) +;; CHECK-NEXT: (loop $while-in1 +;; CHECK-NEXT: (i32.store8 +;; CHECK-NEXT: (local.tee $2 +;; CHECK-NEXT: (i32.sub +;; CHECK-NEXT: (local.get $2) +;; CHECK-NEXT: (i32.const 1) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (i32.or +;; CHECK-NEXT: (i32.rem_u +;; CHECK-NEXT: (local.get $0) +;; CHECK-NEXT: (i32.const 10) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (i32.const 48) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (local.set $1 +;; CHECK-NEXT: (i32.div_u +;; CHECK-NEXT: (local.get $0) +;; CHECK-NEXT: (i32.const 10) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (if +;; CHECK-NEXT: (i32.ge_u +;; CHECK-NEXT: (local.get $0) +;; CHECK-NEXT: (i32.const 10) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (block +;; CHECK-NEXT: (local.set $0 +;; CHECK-NEXT: (local.get $1) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (br $while-in1) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) diff --git a/test/lit/passes/inlining_splitting.wast b/test/lit/passes/inlining_splitting.wast new file mode 100644 index 000000000..98168527a --- /dev/null +++ b/test/lit/passes/inlining_splitting.wast @@ -0,0 +1,1702 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. + +;; RUN: foreach %s %t wasm-opt --inlining --optimize-level=3 --all-features -S -o - | filecheck %s + +(module + ;; CHECK: (type $none_=>_none (func)) + + ;; CHECK: (type $i32_=>_none (func (param i32))) + + ;; CHECK: (type $anyref_=>_anyref (func (param anyref) (result anyref))) + + ;; CHECK: (type $anyref_=>_none (func (param anyref))) + + ;; CHECK: (type $struct (struct )) + (type $struct (struct)) + + ;; CHECK: (type $i32_rtt_$struct_=>_none (func (param i32 (rtt $struct)))) + + ;; CHECK: (type $i64_i32_f64_=>_none (func (param i64 i32 f64))) + + ;; CHECK: (import "out" "func" (func $import)) + (import "out" "func" (func $import)) + + ;; CHECK: (global $glob i32 (i32.const 1)) + (global $glob i32 (i32.const 1)) + + ;; CHECK: (start $start-used-globally) + (start $start-used-globally) + + ;; Pattern A: functions beginning with + ;; + ;; if (simple) return; + + (func $maybe-work-hard (param $x i32) + ;; A function that does a quick check before any heavy work. We can outline + ;; the heavy work, so that the condition can be inlined. + ;; + ;; This function (and others lower down that we also optimize) will vanish + ;; in the output. Part of it will be inlined into its caller, below, and + ;; the rest will be outlined into a new function with suffix "outlined". + (if + (local.get $x) + (return) + ) + (loop $l + (call $import) + (br $l) + ) + ) + + ;; CHECK: (func $call-maybe-work-hard + ;; CHECK-NEXT: (local $0 i32) + ;; CHECK-NEXT: (local $1 i32) + ;; CHECK-NEXT: (local $2 i32) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$maybe-work-hard + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$maybe-work-hard + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$maybe-work-hard0 + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$maybe-work-hard + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$maybe-work-hard1 + ;; CHECK-NEXT: (local.set $2 + ;; CHECK-NEXT: (i32.const 3) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$maybe-work-hard + ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-maybe-work-hard + ;; Call the above function to verify that we can in fact inline it after + ;; splitting. We should see each of these three calls replaced by inlined + ;; code performing the if from $maybe-work-hard, and depending on that + ;; result they each call the outlined code that must *not* be inlined. + ;; + ;; Note that we must call more than once, otherwise given a single use we + ;; will always inline the entire thing. + (call $maybe-work-hard (i32.const 1)) + (call $maybe-work-hard (i32.const 2)) + (call $maybe-work-hard (i32.const 3)) + ) + + (func $just-if (param $x i32) + ;; As above, but all we have is an if. + (if + (local.get $x) + (loop $l + (call $import) + (br_if $l + (local.get $x) + ) + ) + ) + ) + + ;; CHECK: (func $call-just-if + ;; CHECK-NEXT: (local $0 i32) + ;; CHECK-NEXT: (local $1 i32) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$just-if + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (call $byn-split-outlined-B$just-if + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$just-if0 + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: (call $byn-split-outlined-B$just-if + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-just-if + (call $just-if (i32.const 1)) + (call $just-if (i32.const 2)) + ) + + ;; CHECK: (func $br-to-toplevel (param $x i32) + ;; CHECK-NEXT: (block $toplevel + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (block $block + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (br $toplevel) + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $br-to-toplevel (param $x i32) + (block $toplevel + (if + (local.get $x) + (block + (if + (local.get $x) + ;; A br to the toplevel block prevents us from outlining this code, + ;; as we can't outline a br without its target. + (br $toplevel) + (call $import) + ) + ) + ) + ) + ) + + ;; CHECK: (func $call-br-to-toplevel + ;; CHECK-NEXT: (call $br-to-toplevel + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $br-to-toplevel + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-br-to-toplevel + (call $br-to-toplevel (i32.const 1)) + (call $br-to-toplevel (i32.const 2)) + ) + + ;; CHECK: (func $nondefaultable-param (param $x i32) (param $y (rtt $struct)) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (return) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (loop $l + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: (br $l) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $nondefaultable-param (param $x i32) (param $y (rtt $struct)) + ;; The RTT param here prevents us from even being inlined, even with + ;; splitting. + (if + (local.get $x) + (return) + ) + (loop $l + (call $import) + (br $l) + ) + ) + + ;; CHECK: (func $call-nondefaultable-param + ;; CHECK-NEXT: (call $nondefaultable-param + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (rtt.canon $struct) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-nondefaultable-param + (call $nondefaultable-param (i32.const 0) (rtt.canon $struct)) + ) + + (func $many-params (param $x i64) (param $y i32) (param $z f64) + ;; Test that we can optimize this function even though it has multiple + ;; parameters, and it is not the very first one that we use in the + ;; condition. + (if + (local.get $y) + (return) + ) + (loop $l + (call $import) + (br $l) + ) + ) + + ;; CHECK: (func $call-many-params + ;; CHECK-NEXT: (local $0 i64) + ;; CHECK-NEXT: (local $1 i32) + ;; CHECK-NEXT: (local $2 f64) + ;; CHECK-NEXT: (local $3 i64) + ;; CHECK-NEXT: (local $4 i32) + ;; CHECK-NEXT: (local $5 f64) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$many-params + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (i64.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $2 + ;; CHECK-NEXT: (f64.const 3.14159) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$many-params + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: (local.get $2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$many-params0 + ;; CHECK-NEXT: (local.set $3 + ;; CHECK-NEXT: (i64.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $4 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $5 + ;; CHECK-NEXT: (f64.const 3.14159) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (local.get $4) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$many-params + ;; CHECK-NEXT: (local.get $3) + ;; CHECK-NEXT: (local.get $4) + ;; CHECK-NEXT: (local.get $5) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-many-params + ;; Call the above function to verify that we can in fact inline it after + ;; splitting. We should see each of these three calls replaced by inlined + ;; code performing the if from $maybe-work-hard, and depending on that + ;; result they each call the outlined code that must *not* be inlined. + (call $many-params (i64.const 0) (i32.const 1) (f64.const 3.14159)) + (call $many-params (i64.const 0) (i32.const 1) (f64.const 3.14159)) + ) + + (func $condition-eqz (param $x i32) + (if + ;; More work in the condition, but work that we still consider worth + ;; optimizing: a unary op. + (i32.eqz + (local.get $x) + ) + (return) + ) + (loop $l + (call $import) + (br $l) + ) + ) + + ;; CHECK: (func $call-condition-eqz + ;; CHECK-NEXT: (local $0 i32) + ;; CHECK-NEXT: (local $1 i32) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-eqz + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$condition-eqz + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-eqz0 + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$condition-eqz + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-condition-eqz + (call $condition-eqz (i32.const 0)) + (call $condition-eqz (i32.const 1)) + ) + + (func $condition-global + (if + ;; A global read, also worth splitting. + (global.get $glob) + (return) + ) + (loop $l + (call $import) + (br $l) + ) + ) + + ;; CHECK: (func $call-condition-global + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-global + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (global.get $glob) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$condition-global) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-global0 + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (global.get $glob) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$condition-global) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-condition-global + (call $condition-global) + (call $condition-global) + ) + + (func $condition-ref.is (param $x anyref) + (if + ;; A ref.is operation. + (ref.is_null + (local.get $x) + ) + (return) + ) + (loop $l + (call $import) + (br $l) + ) + ) + + ;; CHECK: (func $call-condition-ref.is + ;; CHECK-NEXT: (local $0 anyref) + ;; CHECK-NEXT: (local $1 anyref) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-ref.is + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$condition-ref.is + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$condition-ref.is0 + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$condition-ref.is + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-condition-ref.is + (call $condition-ref.is (ref.null any)) + (call $condition-ref.is (ref.null any)) + ) + + ;; CHECK: (func $condition-disallow-binary (param $x i32) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (loop $l + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: (br $l) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $condition-disallow-binary (param $x i32) + (if + ;; Work we do *not* allow (at least for now), a binary. + (i32.add + (local.get $x) + (local.get $x) + ) + (return) + ) + (loop $l + (call $import) + (br $l) + ) + ) + + ;; CHECK: (func $call-condition-disallow-binary + ;; CHECK-NEXT: (call $condition-disallow-binary + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $condition-disallow-binary + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-condition-disallow-binary + (call $condition-disallow-binary (i32.const 0)) + (call $condition-disallow-binary (i32.const 1)) + ) + + ;; CHECK: (func $condition-disallow-unreachable (param $x i32) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (loop $l + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: (br $l) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $condition-disallow-unreachable (param $x i32) + (if + ;; Work we do *not* allow (at least for now), an unreachable. + (i32.eqz + (unreachable) + ) + (return) + ) + (loop $l + (call $import) + (br $l) + ) + ) + + ;; CHECK: (func $call-condition-disallow-unreachable + ;; CHECK-NEXT: (call $condition-disallow-unreachable + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $condition-disallow-unreachable + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-condition-disallow-unreachable + (call $condition-disallow-unreachable (i32.const 0)) + (call $condition-disallow-unreachable (i32.const 1)) + ) + + ;; CHECK: (func $start-used-globally + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (global.get $glob) + ;; CHECK-NEXT: (return) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (loop $l + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: (br $l) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $start-used-globally + ;; This is optimizable even though it is the start function, that is is, + ;; having global uses of a function are not a problem for partial inlining + ;; (since we do not modify this function - we create new split pieces of + ;; it). + (if + (global.get $glob) + (return) + ) + (loop $l + (call $import) + (br $l) + ) + ) + + ;; CHECK: (func $call-start-used-globally + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$start-used-globally + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (global.get $glob) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$start-used-globally) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$start-used-globally0 + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (global.get $glob) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$start-used-globally) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-start-used-globally + (call $start-used-globally) + (call $start-used-globally) + ) + + (func $inlineable + ;; This looks optimizable, but it is also inlineable - so we do not need to + ;; split it. It will just be inlined directly, without any $outlined part + ;; that is split out. + (if + (global.get $glob) + (return) + ) + ) + + ;; CHECK: (func $call-inlineable + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$inlineable + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (global.get $glob) + ;; CHECK-NEXT: (br $__inlined_func$inlineable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$inlineable0 + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (global.get $glob) + ;; CHECK-NEXT: (br $__inlined_func$inlineable0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-inlineable + (call $inlineable) + (call $inlineable) + ) + + ;; CHECK: (func $if-not-first (param $x i32) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (return) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (loop $l + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: (br $l) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $if-not-first (param $x i32) + ;; Except for the initial nop, we should outline this. As the if is not + ;; first any more, we ignore it. + (nop) + (if + (local.get $x) + (return) + ) + (loop $l + (call $import) + (br $l) + ) + ) + + ;; CHECK: (func $call-if-not-first + ;; CHECK-NEXT: (call $if-not-first + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $if-not-first + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-if-not-first + (call $if-not-first (i32.const 0)) + (call $if-not-first (i32.const 1)) + ) + + ;; CHECK: (func $if-else (param $x i32) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (return) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (loop $l + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: (br $l) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $if-else (param $x i32) + ;; An else in the if prevents us from recognizing the pattern we want. + (if + (local.get $x) + (return) + (nop) + ) + (loop $l + (call $import) + (br $l) + ) + ) + + ;; CHECK: (func $call-if-else + ;; CHECK-NEXT: (call $if-else + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $if-else + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-if-else + (call $if-else (i32.const 0)) + (call $if-else (i32.const 1)) + ) + + ;; CHECK: (func $if-non-return (param $x i32) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (loop $l + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: (br $l) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $if-non-return (param $x i32) + ;; Something other than a return in the if body prevents us from outlining. + (if + (local.get $x) + (unreachable) + ) + (loop $l + (call $import) + (br $l) + ) + ) + + ;; CHECK: (func $call-if-non-return + ;; CHECK-NEXT: (call $if-non-return + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $if-non-return + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-if-non-return + (call $if-non-return (i32.const 0)) + (call $if-non-return (i32.const 1)) + ) + + (func $colliding-name (param $x i32) + ;; When we outline this, the name should not collide with that of the + ;; function after us. + (if + (local.get $x) + (return) + ) + (loop $l + (call $import) + (br $l) + ) + ) + + ;; CHECK: (func $call-colliding-name + ;; CHECK-NEXT: (local $0 i32) + ;; CHECK-NEXT: (local $1 i32) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$colliding-name + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$colliding-name_0 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$colliding-name0 + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$colliding-name_0 + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-colliding-name + (call $colliding-name (i32.const 0)) + (call $colliding-name (i32.const 1)) + ) + + ;; CHECK: (func $byn-split-outlined-A$colliding-name + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $byn-split-outlined-A$colliding-name + ;; This function's name might collide with the split function we create for + ;; the above function; the split function's name must be fixed up. + ) + + ;; Pattern B: functions containing + ;; + ;; if (simple1) heavy-work-that-is-unreachable; + ;; if (simple..) heavy-work-that-is-unreachable; + ;; simplek + + (func $error-if-null (param $x anyref) (result anyref) + ;; A "as non null" function: If the input is null, issue an error somehow + ;; (here, by calling an import, but could also be a throwing of an + ;; exception). If not null, return the value. + (if + (ref.is_null + (local.get $x) + ) + (block + (call $import) + (unreachable) + ) + ) + (local.get $x) + ) + + ;; CHECK: (func $call-error-if-null + ;; CHECK-NEXT: (local $0 anyref) + ;; CHECK-NEXT: (local $1 anyref) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result anyref) + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$error-if-null (result anyref) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block (result anyref) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $__inlined_func$byn-split-inlineable-B$error-if-null + ;; CHECK-NEXT: (call $byn-split-outlined-B$error-if-null + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result anyref) + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$error-if-null0 (result anyref) + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block (result anyref) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (br $__inlined_func$byn-split-inlineable-B$error-if-null0 + ;; CHECK-NEXT: (call $byn-split-outlined-B$error-if-null + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-error-if-null + (drop (call $error-if-null (ref.null any))) + (drop (call $error-if-null (ref.null any))) + ) + + ;; CHECK: (func $too-many (param $x anyref) (result anyref) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $block + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + (func $too-many (param $x anyref) (result anyref) + (if + (ref.is_null + (local.get $x) + ) + (block + (call $import) + (unreachable) + ) + ) + (nop) ;; An extra operation here prevents us from identifying the pattern. + (local.get $x) + ) + + ;; CHECK: (func $call-too-many + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $too-many + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $too-many + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-too-many + (drop (call $too-many (ref.null any))) + (drop (call $too-many (ref.null any))) + ) + + ;; CHECK: (func $tail-not-simple (param $x anyref) (result anyref) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $block + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $tail-not-simple (param $x anyref) (result anyref) + (if + (ref.is_null + (local.get $x) + ) + (block + (call $import) + (unreachable) + ) + ) + (unreachable) ;; This prevents us from optimizing + ) + + ;; CHECK: (func $call-tail-not-simple + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $tail-not-simple + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $tail-not-simple + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-tail-not-simple + (drop (call $tail-not-simple (ref.null any))) + (drop (call $tail-not-simple (ref.null any))) + ) + + (func $reachable-if-body (param $x anyref) (result anyref) + (if + (ref.is_null + (local.get $x) + ) + ;; It is ok if the body is not unreachable (so long as it contains no + ;; returns). We will optimize this, and just do a call to the outlined + ;; code, without a return of a value here. + (call $import) + ) + (local.get $x) + ) + + ;; CHECK: (func $call-reachable-if-body + ;; CHECK-NEXT: (local $0 anyref) + ;; CHECK-NEXT: (local $1 anyref) + ;; CHECK-NEXT: (local $2 anyref) + ;; CHECK-NEXT: (local $3 anyref) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result anyref) + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$reachable-if-body (result anyref) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block (result anyref) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $__inlined_func$byn-split-outlined-B$reachable-if-body + ;; CHECK-NEXT: (local.set $2 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result anyref) + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$reachable-if-body0 (result anyref) + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block (result anyref) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $__inlined_func$byn-split-outlined-B$reachable-if-body0 + ;; CHECK-NEXT: (local.set $3 + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-reachable-if-body + ;; Note that the above contains + ;; + ;; (block $__inlined_func$byn-split-outlined-B$reachable-if-body + ;; + ;; which indicates that we've inlined the outlined function. That seems odd, + ;; but it is the result of the if's body being just a call. When we outline, + ;; we end up with a function that all it does is make that call - which is + ;; worth inlining in the normal way (to avoid two calls). As a result of all + ;; that, we end up inlining *all* of $reachable-if-body, just by a + ;; roundabout way (split, outline, then inline). While this seems odd, each + ;; step along the way makes sense, and the result is a good one (might be a + ;; little hard to see before opts remove the extra block cruft etc.). + ;; + ;; We could avoid this if we detected that the if body is just a call, and + ;; not done any outlining - just done that call. That would be more + ;; efficient, but it would make the code more complicated, and the result is + ;; the same. + (drop (call $reachable-if-body (ref.null any))) + (drop (call $reachable-if-body (ref.null any))) + ) + + ;; CHECK: (func $reachable-if-body-return (param $x anyref) (result anyref) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + (func $reachable-if-body-return (param $x anyref) (result anyref) + (if + (ref.is_null + (local.get $x) + ) + (if + (i32.const 1) + ;; The return here prevents the optimization. + (return + (local.get $x) + ) + (call $import) + ) + ) + (local.get $x) + ) + + ;; CHECK: (func $call-reachable-if-body-return + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $reachable-if-body-return + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $reachable-if-body-return + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-reachable-if-body-return + (drop (call $reachable-if-body-return (ref.null any))) + (drop (call $reachable-if-body-return (ref.null any))) + ) + + (func $unreachable-if-body-no-result (param $x anyref) + (if + (ref.is_null + (local.get $x) + ) + ;; The if body is unreachable, but the function has no returned value. + ;; When we outline this code, we should not try to return a value. + (block + (call $import) + (unreachable) + ) + ) + ) + + ;; CHECK: (func $call-unreachable-if-body-no-result + ;; CHECK-NEXT: (local $0 anyref) + ;; CHECK-NEXT: (local $1 anyref) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$unreachable-if-body-no-result + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-B$unreachable-if-body-no-result + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$unreachable-if-body-no-result0 + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-B$unreachable-if-body-no-result + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-unreachable-if-body-no-result + (call $unreachable-if-body-no-result (ref.null any)) + (call $unreachable-if-body-no-result (ref.null any)) + ) + + (func $multi-if (param $x anyref) (result anyref) + (if + (ref.is_null + (local.get $x) + ) + (call $import) + ) + ;; A second if. We can outline both if bodies. + (if + (ref.is_func + (local.get $x) + ) + (loop $x + (call $import) + (br_if $x + (global.get $glob) + ) + ) + ) + (local.get $x) + ) + + ;; CHECK: (func $call-multi-if + ;; CHECK-NEXT: (local $0 anyref) + ;; CHECK-NEXT: (local $1 anyref) + ;; CHECK-NEXT: (local $2 anyref) + ;; CHECK-NEXT: (local $3 anyref) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result anyref) + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$multi-if (result anyref) + ;; CHECK-NEXT: (local.set $0 + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block (result anyref) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $__inlined_func$byn-split-outlined-B$multi-if + ;; CHECK-NEXT: (local.set $2 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_func + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-B$multi-if_0 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block (result anyref) + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-B$multi-if0 (result anyref) + ;; CHECK-NEXT: (local.set $1 + ;; CHECK-NEXT: (ref.null func) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block (result anyref) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $__inlined_func$byn-split-outlined-B$multi-if0 + ;; CHECK-NEXT: (local.set $3 + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_func + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-B$multi-if_0 + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-multi-if + (drop (call $multi-if (ref.null any))) + (drop (call $multi-if (ref.null func))) + ) + + ;; CHECK: (func $too-many-ifs (param $x anyref) (result anyref) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (ref.is_null + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $import) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + (func $too-many-ifs (param $x anyref) (result anyref) + ;; 5 ifs, which is too many. + (if + (ref.is_null + (local.get $x) + ) + (call $import) + ) + (if + (ref.is_null + (local.get $x) + ) + (call $import) + ) + (if + (ref.is_null + (local.get $x) + ) + (call $import) + ) + (if + (ref.is_null + (local.get $x) + ) + (call $import) + ) + (if + (ref.is_null + (local.get $x) + ) + (call $import) + ) + (local.get $x) + ) + + ;; CHECK: (func $call-too-many-ifs + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $too-many-ifs + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $too-many-ifs + ;; CHECK-NEXT: (ref.null func) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $call-too-many-ifs + (drop (call $too-many-ifs (ref.null any))) + (drop (call $too-many-ifs (ref.null func))) + ) +) + +;; CHECK: (func $byn-split-outlined-A$maybe-work-hard (param $x i32) +;; CHECK-NEXT: (loop $l +;; CHECK-NEXT: (call $import) +;; CHECK-NEXT: (br $l) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + +;; CHECK: (func $byn-split-outlined-B$just-if (param $x i32) +;; CHECK-NEXT: (loop $l +;; CHECK-NEXT: (call $import) +;; CHECK-NEXT: (br_if $l +;; CHECK-NEXT: (local.get $x) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + +;; CHECK: (func $byn-split-outlined-A$many-params (param $x i64) (param $y i32) (param $z f64) +;; CHECK-NEXT: (loop $l +;; CHECK-NEXT: (call $import) +;; CHECK-NEXT: (br $l) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + +;; CHECK: (func $byn-split-outlined-A$condition-eqz (param $x i32) +;; CHECK-NEXT: (loop $l +;; CHECK-NEXT: (call $import) +;; CHECK-NEXT: (br $l) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + +;; CHECK: (func $byn-split-outlined-A$condition-global +;; CHECK-NEXT: (loop $l +;; CHECK-NEXT: (call $import) +;; CHECK-NEXT: (br $l) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + +;; CHECK: (func $byn-split-outlined-A$condition-ref.is (param $x anyref) +;; CHECK-NEXT: (loop $l +;; CHECK-NEXT: (call $import) +;; CHECK-NEXT: (br $l) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + +;; CHECK: (func $byn-split-outlined-A$start-used-globally +;; CHECK-NEXT: (loop $l +;; CHECK-NEXT: (call $import) +;; CHECK-NEXT: (br $l) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + +;; CHECK: (func $byn-split-outlined-A$colliding-name_0 (param $x i32) +;; CHECK-NEXT: (loop $l +;; CHECK-NEXT: (call $import) +;; CHECK-NEXT: (br $l) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + +;; CHECK: (func $byn-split-outlined-B$error-if-null (param $x anyref) (result anyref) +;; CHECK-NEXT: (block $block +;; CHECK-NEXT: (call $import) +;; CHECK-NEXT: (unreachable) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + +;; CHECK: (func $byn-split-outlined-B$unreachable-if-body-no-result (param $x anyref) +;; CHECK-NEXT: (block $block +;; CHECK-NEXT: (call $import) +;; CHECK-NEXT: (unreachable) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + +;; CHECK: (func $byn-split-outlined-B$multi-if_0 (param $x anyref) +;; CHECK-NEXT: (loop $x +;; CHECK-NEXT: (call $import) +;; CHECK-NEXT: (br_if $x +;; CHECK-NEXT: (global.get $glob) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +(module + ;; CHECK: (type $none_=>_none (func)) + (type $none_=>_none (func)) + ;; CHECK: (global $global$0 (mut i32) (i32.const 10)) + (global $global$0 (mut i32) (i32.const 10)) + ;; CHECK: (export "0" (func $0)) + (export "0" (func $0)) + ;; CHECK: (export "1" (func $1)) + (export "1" (func $1)) + ;; CHECK: (func $0 + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (global.get $global$0) + ;; CHECK-NEXT: (return) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$1 + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (call $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$10 + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (call $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $0 + ;; A function that is a good candidate to partially inline. + (if + (global.get $global$0) + (return) + ) + (call $1) + (call $1) + ) + ;; CHECK: (func $1 + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$0 + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (global.get $global$0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block $__inlined_func$byn-split-outlined-A$0 + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$1 + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$00 + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (global.get $global$0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$10 + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$01 + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (i32.eqz + ;; CHECK-NEXT: (global.get $global$0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $byn-split-outlined-A$0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $1 + ;; This and the previous function are mutually recursive. As a result, we + ;; can keep partially inlining between them, creating new functions as we + ;; go, even though that is not very useful. + (call $0) + ) + + ;; Add a lot more functions, so the # of functions is high which would + ;; otherwise limit the # of iterations that we run. + ;; CHECK: (func $2 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $2 + (nop) + ) + ;; CHECK: (func $3 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $3 + (nop) + ) + ;; CHECK: (func $4 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $4 + (nop) + ) + ;; CHECK: (func $5 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $5 + (nop) + ) + ;; CHECK: (func $6 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $6 + (nop) + ) + ;; CHECK: (func $7 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $7 + (nop) + ) + ;; CHECK: (func $8 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $8 + (nop) + ) + ;; CHECK: (func $9 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $9 + (nop) + ) + ;; CHECK: (func $10 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $10 + (nop) + ) + ;; CHECK: (func $11 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $11 + (nop) + ) + ;; CHECK: (func $12 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $12 + (nop) + ) + ;; CHECK: (func $13 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $13 + (nop) + ) + ;; CHECK: (func $14 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $14 + (nop) + ) + ;; CHECK: (func $15 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $15 + (nop) + ) + ;; CHECK: (func $16 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $16 + (nop) + ) + ;; CHECK: (func $17 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $17 + (nop) + ) + ;; CHECK: (func $18 + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $18 + (nop) + ) +) +;; CHECK: (func $byn-split-outlined-A$0 +;; CHECK-NEXT: (block +;; CHECK-NEXT: (block $__inlined_func$1 +;; CHECK-NEXT: (block +;; CHECK-NEXT: (block +;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$0 +;; CHECK-NEXT: (if +;; CHECK-NEXT: (i32.eqz +;; CHECK-NEXT: (global.get $global$0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (call $byn-split-outlined-A$0_0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (block +;; CHECK-NEXT: (block $__inlined_func$10 +;; CHECK-NEXT: (block +;; CHECK-NEXT: (block +;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$00 +;; CHECK-NEXT: (if +;; CHECK-NEXT: (i32.eqz +;; CHECK-NEXT: (global.get $global$0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (call $byn-split-outlined-A$0_0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + +;; CHECK: (func $byn-split-outlined-A$0_0 +;; CHECK-NEXT: (block +;; CHECK-NEXT: (block $__inlined_func$1 +;; CHECK-NEXT: (block +;; CHECK-NEXT: (block +;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$0 +;; CHECK-NEXT: (if +;; CHECK-NEXT: (i32.eqz +;; CHECK-NEXT: (global.get $global$0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (call $byn-split-outlined-A$0_1) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (block +;; CHECK-NEXT: (block $__inlined_func$10 +;; CHECK-NEXT: (block +;; CHECK-NEXT: (block +;; CHECK-NEXT: (block $__inlined_func$byn-split-inlineable-A$00 +;; CHECK-NEXT: (if +;; CHECK-NEXT: (i32.eqz +;; CHECK-NEXT: (global.get $global$0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (call $byn-split-outlined-A$0_1) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) + +;; CHECK: (func $byn-split-outlined-A$0_1 +;; CHECK-NEXT: (block +;; CHECK-NEXT: (block $__inlined_func$1 +;; CHECK-NEXT: (block +;; CHECK-NEXT: (call $0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: (block +;; CHECK-NEXT: (block $__inlined_func$10 +;; CHECK-NEXT: (block +;; CHECK-NEXT: (call $0) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) +;; CHECK-NEXT: ) |