summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/fuzz_opt.py1
-rw-r--r--src/ir/module-utils.h12
-rw-r--r--src/passes/Inlining.cpp628
-rw-r--r--test/lit/passes/inlining-optimizing_optimize-level=3.wast1201
-rw-r--r--test/lit/passes/inlining_splitting.wast1702
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: )