summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/CMakeLists.txt1
-rw-r--r--src/passes/Inlining.cpp22
-rw-r--r--src/passes/NoInline.cpp77
-rw-r--r--src/passes/pass.cpp7
-rw-r--r--src/passes/passes.h3
-rw-r--r--src/wasm.h6
-rw-r--r--test/lit/help/wasm-opt.test8
-rw-r--r--test/lit/help/wasm2js.test8
-rw-r--r--test/lit/passes/no-inline.wast925
9 files changed, 1049 insertions, 8 deletions
diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt
index 53f52e23f..279c50983 100644
--- a/src/passes/CMakeLists.txt
+++ b/src/passes/CMakeLists.txt
@@ -70,6 +70,7 @@ set(passes_SOURCES
MultiMemoryLowering.cpp
NameList.cpp
NameTypes.cpp
+ NoInline.cpp
OnceReduction.cpp
OptimizeAddedConstants.cpp
OptimizeCasts.cpp
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp
index 20172d88d..e1e2dd022 100644
--- a/src/passes/Inlining.cpp
+++ b/src/passes/Inlining.cpp
@@ -686,8 +686,10 @@ struct FunctionSplitter {
auto outlinedFunctionSize = info.size - Measurer::measure(iff);
// If outlined function will be worth normal inline, skip the intermediate
- // state and inline fully now.
- if (outlinedFunctionWorthInlining(info, outlinedFunctionSize)) {
+ // state and inline fully now. Note that if full inlining is disabled we
+ // will not do this, and instead inline partially.
+ if (!func->noFullInline &&
+ outlinedFunctionWorthInlining(info, outlinedFunctionSize)) {
return InliningMode::Full;
}
@@ -771,10 +773,12 @@ struct FunctionSplitter {
// Success, this matches the pattern.
// If the outlined function will be worth inlining normally, skip the
- // intermediate state and inline fully now.
+ // intermediate state and inline fully now. (As above, if full inlining is
+ // disabled, we only partially inline.)
if (numIfs == 1) {
auto outlinedFunctionSize = Measurer::measure(iff->ifTrue);
- if (outlinedFunctionWorthInlining(info, outlinedFunctionSize)) {
+ if (!func->noFullInline &&
+ outlinedFunctionWorthInlining(info, outlinedFunctionSize)) {
return InliningMode::Full;
}
}
@@ -1197,7 +1201,9 @@ struct Inlining : public Pass {
// See explanation in doInlining() for the parameter nameHint.
Index inlinedNameHint = 0;
+ // Decide for a given function whether to inline, and if so in what mode.
InliningMode getInliningMode(Name name) {
+ auto* func = module->getFunction(name);
auto& info = infos[name];
if (info.inliningMode != InliningMode::Unknown) {
@@ -1205,19 +1211,19 @@ struct Inlining : public Pass {
}
// Check if the function itself is worth inlining as it is.
- if (info.worthFullInlining(getPassOptions())) {
- info.inliningMode = InliningMode::Full;
- return info.inliningMode;
+ if (!func->noFullInline && info.worthFullInlining(getPassOptions())) {
+ return info.inliningMode = InliningMode::Full;
}
// Otherwise, check if we can at least inline part of it, if we are
// interested in such things.
- if (functionSplitter) {
+ if (!func->noPartialInline && functionSplitter) {
info.inliningMode = functionSplitter->getSplitDrivenInliningMode(
module->getFunction(name), info);
return info.inliningMode;
}
+ // Cannot be fully or partially inlined => uninlineable.
info.inliningMode = InliningMode::Uninlineable;
return info.inliningMode;
}
diff --git a/src/passes/NoInline.cpp b/src/passes/NoInline.cpp
new file mode 100644
index 000000000..59e4f7e2c
--- /dev/null
+++ b/src/passes/NoInline.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2023 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// Mark functions as no-inline based on name wildcards. For example:
+//
+// --no-inline=*leave-alone* --inlining
+//
+// That will mark all functions with names like "runtime-leave-alone-1234" as
+// no-inline, and as a result the inlining pass that happens afterwards will not
+// inline them.
+//
+// Note that this is itself a pass, which does work - it marks things in the
+// IR - and so the order of operations matters. If we did
+//
+// --inlining --no-inline=*leave-alone*
+//
+// then we'd first perform the inlining and then the marking, which would mean
+// the marking has no effect.
+//
+
+#include "pass.h"
+#include "support/string.h"
+#include "wasm.h"
+
+namespace wasm {
+
+namespace {
+
+enum NoInlineMode { Full = 0, Partial = 1, Both = 2 };
+
+struct NoInline : public Pass {
+ NoInlineMode mode;
+
+ NoInline(NoInlineMode mode) : mode(mode) {}
+
+ void run(Module* module) override {
+ std::string pattern = getPassOptions().getArgument(
+ name, "Usage usage: wasm-opt --" + name + "=WILDCARD");
+
+ for (auto& func : module->functions) {
+ if (!String::wildcardMatch(pattern, func->name.toString())) {
+ continue;
+ }
+
+ if (mode == Full || mode == Both) {
+ func->noFullInline = true;
+ }
+ if (mode == Partial || mode == Both) {
+ func->noPartialInline = true;
+ }
+ }
+ }
+};
+
+} // anonymous namespace
+
+Pass* createNoInlinePass() { return new NoInline(NoInlineMode::Both); }
+Pass* createNoFullInlinePass() { return new NoInline(NoInlineMode::Full); }
+Pass* createNoPartialInlinePass() {
+ return new NoInline(NoInlineMode::Partial);
+}
+
+} // namespace wasm
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index 38b6c73a6..525248924 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -294,6 +294,13 @@ void PassRegistry::registerPasses() {
createMultiMemoryLoweringWithBoundsChecksPass);
registerPass("nm", "name list", createNameListPass);
registerPass("name-types", "(re)name all heap types", createNameTypesPass);
+ registerPass("no-inline", "mark functions as no-inline", createNoInlinePass);
+ registerPass("no-full-inline",
+ "mark functions as no-inline (for full inlining only)",
+ createNoFullInlinePass);
+ registerPass("no-partial-inline",
+ "mark functions as no-inline (for partial inlining only)",
+ createNoPartialInlinePass);
registerPass("once-reduction",
"reduces calls to code that only runs once",
createOnceReductionPass);
diff --git a/src/passes/passes.h b/src/passes/passes.h
index b0b42d5de..e6ff7709e 100644
--- a/src/passes/passes.h
+++ b/src/passes/passes.h
@@ -92,6 +92,9 @@ Pass* createMultiMemoryLoweringPass();
Pass* createMultiMemoryLoweringWithBoundsChecksPass();
Pass* createNameListPass();
Pass* createNameTypesPass();
+Pass* createNoInlinePass();
+Pass* createNoFullInlinePass();
+Pass* createNoPartialInlinePass();
Pass* createOnceReductionPass();
Pass* createOptimizeAddedConstantsPass();
Pass* createOptimizeAddedConstantsPropagatePass();
diff --git a/src/wasm.h b/src/wasm.h
index a7a2e0b1e..24138c99d 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -2072,6 +2072,12 @@ public:
delimiterLocations;
BinaryLocations::FunctionLocations funcLocation;
+ // Inlining metadata: whether to disallow full and/or partial inlining (for
+ // details on what those mean, see Inlining.cpp).
+ bool noFullInline = false;
+ bool noPartialInline = false;
+
+ // Methods
Signature getSig() { return type.getSignature(); }
Type getParams() { return getSig().params; }
Type getResults() { return getSig().results; }
diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test
index b18c312ff..a45096e39 100644
--- a/test/lit/help/wasm-opt.test
+++ b/test/lit/help/wasm-opt.test
@@ -297,6 +297,14 @@
;; CHECK-NEXT:
;; CHECK-NEXT: --nm name list
;; CHECK-NEXT:
+;; CHECK-NEXT: --no-full-inline mark functions as no-inline (for
+;; CHECK-NEXT: full inlining only)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --no-inline mark functions as no-inline
+;; CHECK-NEXT:
+;; CHECK-NEXT: --no-partial-inline mark functions as no-inline (for
+;; CHECK-NEXT: partial inlining only)
+;; CHECK-NEXT:
;; CHECK-NEXT: --once-reduction reduces calls to code that only
;; CHECK-NEXT: runs once
;; CHECK-NEXT:
diff --git a/test/lit/help/wasm2js.test b/test/lit/help/wasm2js.test
index 129374049..9303642be 100644
--- a/test/lit/help/wasm2js.test
+++ b/test/lit/help/wasm2js.test
@@ -256,6 +256,14 @@
;; CHECK-NEXT:
;; CHECK-NEXT: --nm name list
;; CHECK-NEXT:
+;; CHECK-NEXT: --no-full-inline mark functions as no-inline (for
+;; CHECK-NEXT: full inlining only)
+;; CHECK-NEXT:
+;; CHECK-NEXT: --no-inline mark functions as no-inline
+;; CHECK-NEXT:
+;; CHECK-NEXT: --no-partial-inline mark functions as no-inline (for
+;; CHECK-NEXT: partial inlining only)
+;; CHECK-NEXT:
;; CHECK-NEXT: --once-reduction reduces calls to code that only
;; CHECK-NEXT: runs once
;; CHECK-NEXT:
diff --git a/test/lit/passes/no-inline.wast b/test/lit/passes/no-inline.wast
new file mode 100644
index 000000000..3321dc1ad
--- /dev/null
+++ b/test/lit/passes/no-inline.wast
@@ -0,0 +1,925 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
+
+;; Enable both full and partial inlining, and show how we filter out functions
+;; using --no-*-inline. The functions with "yes" in their names will always be
+;; inlined, while the ones with "maybe" will be filtered out in some modes.
+
+;; RUN: foreach %s %t wasm-opt --inlining --optimize-level=3 --partial-inlining-ifs=1 -S -o - | filecheck %s --check-prefix YES_ALL
+;; RUN: foreach %s %t wasm-opt --no-partial-inline=*maybe* --inlining --optimize-level=3 --partial-inlining-ifs=1 -S -o - | filecheck %s --check-prefix NO_PART
+;; RUN: foreach %s %t wasm-opt --no-full-inline=*maybe* --inlining --optimize-level=3 --partial-inlining-ifs=1 -S -o - | filecheck %s --check-prefix NO_FULL
+;; RUN: foreach %s %t wasm-opt --no-inline=*maybe* --inlining --optimize-level=3 --partial-inlining-ifs=1 -S -o - | filecheck %s --check-prefix NO_BOTH
+
+(module
+ ;; YES_ALL: (type $0 (func))
+
+ ;; YES_ALL: (type $1 (func (param i32)))
+
+ ;; YES_ALL: (import "a" "b" (func $import))
+ ;; NO_PART: (type $0 (func))
+
+ ;; NO_PART: (type $1 (func (param i32)))
+
+ ;; NO_PART: (import "a" "b" (func $import))
+ ;; NO_FULL: (type $0 (func))
+
+ ;; NO_FULL: (type $1 (func (param i32)))
+
+ ;; NO_FULL: (import "a" "b" (func $import))
+ ;; NO_BOTH: (type $0 (func))
+
+ ;; NO_BOTH: (type $1 (func (param i32)))
+
+ ;; NO_BOTH: (import "a" "b" (func $import))
+ (import "a" "b" (func $import))
+
+ (func $full-yes-inline (param $x i32)
+ (call $import)
+ )
+
+ ;; NO_FULL: (func $full-maybe-inline (param $x i32)
+ ;; NO_FULL-NEXT: (call $import)
+ ;; NO_FULL-NEXT: )
+ ;; NO_BOTH: (func $full-maybe-inline (param $x i32)
+ ;; NO_BOTH-NEXT: (call $import)
+ ;; NO_BOTH-NEXT: )
+ (func $full-maybe-inline (param $x i32)
+ (call $import)
+ )
+
+ (func $partial-yes-inline (param $x i32)
+ (if
+ (local.get $x)
+ (return)
+ )
+ (loop $l
+ (call $import)
+ (br $l)
+ )
+ )
+
+ ;; NO_PART: (func $partial-maybe-inline (param $x i32)
+ ;; NO_PART-NEXT: (if
+ ;; NO_PART-NEXT: (local.get $x)
+ ;; NO_PART-NEXT: (return)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (loop $l
+ ;; NO_PART-NEXT: (call $import)
+ ;; NO_PART-NEXT: (br $l)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_BOTH: (func $partial-maybe-inline (param $x i32)
+ ;; NO_BOTH-NEXT: (if
+ ;; NO_BOTH-NEXT: (local.get $x)
+ ;; NO_BOTH-NEXT: (return)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (loop $l
+ ;; NO_BOTH-NEXT: (call $import)
+ ;; NO_BOTH-NEXT: (br $l)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: )
+ (func $partial-maybe-inline (param $x i32)
+ (if
+ (local.get $x)
+ (return)
+ )
+ (loop $l
+ (call $import)
+ (br $l)
+ )
+ )
+
+ ;; YES_ALL: (func $caller
+ ;; YES_ALL-NEXT: (local $0 i32)
+ ;; YES_ALL-NEXT: (local $1 i32)
+ ;; YES_ALL-NEXT: (local $2 i32)
+ ;; YES_ALL-NEXT: (local $3 i32)
+ ;; YES_ALL-NEXT: (block
+ ;; YES_ALL-NEXT: (block $__inlined_func$full-yes-inline
+ ;; YES_ALL-NEXT: (local.set $0
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (call $import)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (block
+ ;; YES_ALL-NEXT: (block $__inlined_func$full-maybe-inline$1
+ ;; YES_ALL-NEXT: (local.set $1
+ ;; YES_ALL-NEXT: (i32.const 1)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (call $import)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (block
+ ;; YES_ALL-NEXT: (block $__inlined_func$byn-split-inlineable-A$partial-yes-inline$2
+ ;; YES_ALL-NEXT: (local.set $2
+ ;; YES_ALL-NEXT: (i32.const 2)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (if
+ ;; YES_ALL-NEXT: (i32.eqz
+ ;; YES_ALL-NEXT: (local.get $2)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (call $byn-split-outlined-A$partial-yes-inline
+ ;; YES_ALL-NEXT: (local.get $2)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (block
+ ;; YES_ALL-NEXT: (block $__inlined_func$byn-split-inlineable-A$partial-maybe-inline$3
+ ;; YES_ALL-NEXT: (local.set $3
+ ;; YES_ALL-NEXT: (i32.const 3)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (if
+ ;; YES_ALL-NEXT: (i32.eqz
+ ;; YES_ALL-NEXT: (local.get $3)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (call $byn-split-outlined-A$partial-maybe-inline
+ ;; YES_ALL-NEXT: (local.get $3)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; NO_PART: (func $caller
+ ;; NO_PART-NEXT: (local $0 i32)
+ ;; NO_PART-NEXT: (local $1 i32)
+ ;; NO_PART-NEXT: (local $2 i32)
+ ;; NO_PART-NEXT: (block
+ ;; NO_PART-NEXT: (block $__inlined_func$full-yes-inline
+ ;; NO_PART-NEXT: (local.set $0
+ ;; NO_PART-NEXT: (i32.const 0)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (call $import)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (block
+ ;; NO_PART-NEXT: (block $__inlined_func$full-maybe-inline$1
+ ;; NO_PART-NEXT: (local.set $1
+ ;; NO_PART-NEXT: (i32.const 1)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (call $import)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (block
+ ;; NO_PART-NEXT: (block $__inlined_func$byn-split-inlineable-A$partial-yes-inline$2
+ ;; NO_PART-NEXT: (local.set $2
+ ;; NO_PART-NEXT: (i32.const 2)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (if
+ ;; NO_PART-NEXT: (i32.eqz
+ ;; NO_PART-NEXT: (local.get $2)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (call $byn-split-outlined-A$partial-yes-inline
+ ;; NO_PART-NEXT: (local.get $2)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (call $partial-maybe-inline
+ ;; NO_PART-NEXT: (i32.const 3)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_FULL: (func $caller
+ ;; NO_FULL-NEXT: (local $0 i32)
+ ;; NO_FULL-NEXT: (local $1 i32)
+ ;; NO_FULL-NEXT: (local $2 i32)
+ ;; NO_FULL-NEXT: (block
+ ;; NO_FULL-NEXT: (block $__inlined_func$full-yes-inline
+ ;; NO_FULL-NEXT: (local.set $0
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (call $import)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (call $full-maybe-inline
+ ;; NO_FULL-NEXT: (i32.const 1)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (block
+ ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-inlineable-A$partial-yes-inline$1
+ ;; NO_FULL-NEXT: (local.set $1
+ ;; NO_FULL-NEXT: (i32.const 2)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (if
+ ;; NO_FULL-NEXT: (i32.eqz
+ ;; NO_FULL-NEXT: (local.get $1)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (call $byn-split-outlined-A$partial-yes-inline
+ ;; NO_FULL-NEXT: (local.get $1)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (block
+ ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-inlineable-A$partial-maybe-inline$2
+ ;; NO_FULL-NEXT: (local.set $2
+ ;; NO_FULL-NEXT: (i32.const 3)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (if
+ ;; NO_FULL-NEXT: (i32.eqz
+ ;; NO_FULL-NEXT: (local.get $2)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (call $byn-split-outlined-A$partial-maybe-inline
+ ;; NO_FULL-NEXT: (local.get $2)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_BOTH: (func $caller
+ ;; NO_BOTH-NEXT: (local $0 i32)
+ ;; NO_BOTH-NEXT: (local $1 i32)
+ ;; NO_BOTH-NEXT: (block
+ ;; NO_BOTH-NEXT: (block $__inlined_func$full-yes-inline
+ ;; NO_BOTH-NEXT: (local.set $0
+ ;; NO_BOTH-NEXT: (i32.const 0)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (call $import)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (call $full-maybe-inline
+ ;; NO_BOTH-NEXT: (i32.const 1)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (block
+ ;; NO_BOTH-NEXT: (block $__inlined_func$byn-split-inlineable-A$partial-yes-inline$1
+ ;; NO_BOTH-NEXT: (local.set $1
+ ;; NO_BOTH-NEXT: (i32.const 2)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (if
+ ;; NO_BOTH-NEXT: (i32.eqz
+ ;; NO_BOTH-NEXT: (local.get $1)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (call $byn-split-outlined-A$partial-yes-inline
+ ;; NO_BOTH-NEXT: (local.get $1)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (call $partial-maybe-inline
+ ;; NO_BOTH-NEXT: (i32.const 3)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: )
+ (func $caller
+ (call $full-yes-inline
+ (i32.const 0)
+ )
+ (call $full-maybe-inline
+ (i32.const 1)
+ )
+ (call $partial-yes-inline
+ (i32.const 2)
+ )
+ (call $partial-maybe-inline
+ (i32.const 3)
+ )
+ )
+
+ ;; YES_ALL: (func $caller-2
+ ;; YES_ALL-NEXT: (local $0 i32)
+ ;; YES_ALL-NEXT: (local $1 i32)
+ ;; YES_ALL-NEXT: (local $2 i32)
+ ;; YES_ALL-NEXT: (local $3 i32)
+ ;; YES_ALL-NEXT: (block
+ ;; YES_ALL-NEXT: (block $__inlined_func$full-yes-inline$4
+ ;; YES_ALL-NEXT: (local.set $0
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (call $import)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (block
+ ;; YES_ALL-NEXT: (block $__inlined_func$full-maybe-inline$5
+ ;; YES_ALL-NEXT: (local.set $1
+ ;; YES_ALL-NEXT: (i32.const 1)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (call $import)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (block
+ ;; YES_ALL-NEXT: (block $__inlined_func$byn-split-inlineable-A$partial-yes-inline$6
+ ;; YES_ALL-NEXT: (local.set $2
+ ;; YES_ALL-NEXT: (i32.const 2)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (if
+ ;; YES_ALL-NEXT: (i32.eqz
+ ;; YES_ALL-NEXT: (local.get $2)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (call $byn-split-outlined-A$partial-yes-inline
+ ;; YES_ALL-NEXT: (local.get $2)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (block
+ ;; YES_ALL-NEXT: (block $__inlined_func$byn-split-inlineable-A$partial-maybe-inline$7
+ ;; YES_ALL-NEXT: (local.set $3
+ ;; YES_ALL-NEXT: (i32.const 3)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (if
+ ;; YES_ALL-NEXT: (i32.eqz
+ ;; YES_ALL-NEXT: (local.get $3)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (call $byn-split-outlined-A$partial-maybe-inline
+ ;; YES_ALL-NEXT: (local.get $3)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; NO_PART: (func $caller-2
+ ;; NO_PART-NEXT: (local $0 i32)
+ ;; NO_PART-NEXT: (local $1 i32)
+ ;; NO_PART-NEXT: (local $2 i32)
+ ;; NO_PART-NEXT: (block
+ ;; NO_PART-NEXT: (block $__inlined_func$full-yes-inline$3
+ ;; NO_PART-NEXT: (local.set $0
+ ;; NO_PART-NEXT: (i32.const 0)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (call $import)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (block
+ ;; NO_PART-NEXT: (block $__inlined_func$full-maybe-inline$4
+ ;; NO_PART-NEXT: (local.set $1
+ ;; NO_PART-NEXT: (i32.const 1)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (call $import)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (block
+ ;; NO_PART-NEXT: (block $__inlined_func$byn-split-inlineable-A$partial-yes-inline$5
+ ;; NO_PART-NEXT: (local.set $2
+ ;; NO_PART-NEXT: (i32.const 2)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (if
+ ;; NO_PART-NEXT: (i32.eqz
+ ;; NO_PART-NEXT: (local.get $2)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (call $byn-split-outlined-A$partial-yes-inline
+ ;; NO_PART-NEXT: (local.get $2)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (call $partial-maybe-inline
+ ;; NO_PART-NEXT: (i32.const 3)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_FULL: (func $caller-2
+ ;; NO_FULL-NEXT: (local $0 i32)
+ ;; NO_FULL-NEXT: (local $1 i32)
+ ;; NO_FULL-NEXT: (local $2 i32)
+ ;; NO_FULL-NEXT: (block
+ ;; NO_FULL-NEXT: (block $__inlined_func$full-yes-inline$3
+ ;; NO_FULL-NEXT: (local.set $0
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (call $import)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (call $full-maybe-inline
+ ;; NO_FULL-NEXT: (i32.const 1)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (block
+ ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-inlineable-A$partial-yes-inline$4
+ ;; NO_FULL-NEXT: (local.set $1
+ ;; NO_FULL-NEXT: (i32.const 2)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (if
+ ;; NO_FULL-NEXT: (i32.eqz
+ ;; NO_FULL-NEXT: (local.get $1)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (call $byn-split-outlined-A$partial-yes-inline
+ ;; NO_FULL-NEXT: (local.get $1)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (block
+ ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-inlineable-A$partial-maybe-inline$5
+ ;; NO_FULL-NEXT: (local.set $2
+ ;; NO_FULL-NEXT: (i32.const 3)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (if
+ ;; NO_FULL-NEXT: (i32.eqz
+ ;; NO_FULL-NEXT: (local.get $2)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (call $byn-split-outlined-A$partial-maybe-inline
+ ;; NO_FULL-NEXT: (local.get $2)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_BOTH: (func $caller-2
+ ;; NO_BOTH-NEXT: (local $0 i32)
+ ;; NO_BOTH-NEXT: (local $1 i32)
+ ;; NO_BOTH-NEXT: (block
+ ;; NO_BOTH-NEXT: (block $__inlined_func$full-yes-inline$2
+ ;; NO_BOTH-NEXT: (local.set $0
+ ;; NO_BOTH-NEXT: (i32.const 0)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (call $import)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (call $full-maybe-inline
+ ;; NO_BOTH-NEXT: (i32.const 1)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (block
+ ;; NO_BOTH-NEXT: (block $__inlined_func$byn-split-inlineable-A$partial-yes-inline$3
+ ;; NO_BOTH-NEXT: (local.set $1
+ ;; NO_BOTH-NEXT: (i32.const 2)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (if
+ ;; NO_BOTH-NEXT: (i32.eqz
+ ;; NO_BOTH-NEXT: (local.get $1)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (call $byn-split-outlined-A$partial-yes-inline
+ ;; NO_BOTH-NEXT: (local.get $1)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (call $partial-maybe-inline
+ ;; NO_BOTH-NEXT: (i32.const 3)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: )
+ (func $caller-2
+ ;; Same as $caller, to prevent the functions from having a single use (which
+ ;; is always inlined).
+ (call $full-yes-inline
+ (i32.const 0)
+ )
+ (call $full-maybe-inline
+ (i32.const 1)
+ )
+ (call $partial-yes-inline
+ (i32.const 2)
+ )
+ (call $partial-maybe-inline
+ (i32.const 3)
+ )
+ )
+)
+
+;; YES_ALL: (func $byn-split-outlined-A$partial-yes-inline (param $x i32)
+;; YES_ALL-NEXT: (loop $l
+;; YES_ALL-NEXT: (call $import)
+;; YES_ALL-NEXT: (br $l)
+;; YES_ALL-NEXT: )
+;; YES_ALL-NEXT: )
+
+;; YES_ALL: (func $byn-split-outlined-A$partial-maybe-inline (param $x i32)
+;; YES_ALL-NEXT: (loop $l
+;; YES_ALL-NEXT: (call $import)
+;; YES_ALL-NEXT: (br $l)
+;; YES_ALL-NEXT: )
+;; YES_ALL-NEXT: )
+
+;; NO_PART: (func $byn-split-outlined-A$partial-yes-inline (param $x i32)
+;; NO_PART-NEXT: (loop $l
+;; NO_PART-NEXT: (call $import)
+;; NO_PART-NEXT: (br $l)
+;; NO_PART-NEXT: )
+;; NO_PART-NEXT: )
+
+;; NO_FULL: (func $byn-split-outlined-A$partial-yes-inline (param $x i32)
+;; NO_FULL-NEXT: (loop $l
+;; NO_FULL-NEXT: (call $import)
+;; NO_FULL-NEXT: (br $l)
+;; NO_FULL-NEXT: )
+;; NO_FULL-NEXT: )
+
+;; NO_FULL: (func $byn-split-outlined-A$partial-maybe-inline (param $x i32)
+;; NO_FULL-NEXT: (loop $l
+;; NO_FULL-NEXT: (call $import)
+;; NO_FULL-NEXT: (br $l)
+;; NO_FULL-NEXT: )
+;; NO_FULL-NEXT: )
+
+;; NO_BOTH: (func $byn-split-outlined-A$partial-yes-inline (param $x i32)
+;; NO_BOTH-NEXT: (loop $l
+;; NO_BOTH-NEXT: (call $import)
+;; NO_BOTH-NEXT: (br $l)
+;; NO_BOTH-NEXT: )
+;; NO_BOTH-NEXT: )
+(module
+ ;; YES_ALL: (type $0 (func))
+
+ ;; YES_ALL: (import "out" "func" (func $import))
+ ;; NO_PART: (type $0 (func))
+
+ ;; NO_PART: (type $1 (func (param i32)))
+
+ ;; NO_PART: (import "out" "func" (func $import))
+ ;; NO_FULL: (type $0 (func))
+
+ ;; NO_FULL: (import "out" "func" (func $import))
+ ;; NO_BOTH: (type $0 (func))
+
+ ;; NO_BOTH: (type $1 (func (param i32)))
+
+ ;; NO_BOTH: (import "out" "func" (func $import))
+ (import "out" "func" (func $import))
+
+ ;; NO_PART: (func $maybe-partial-or-full-1 (param $x i32)
+ ;; NO_PART-NEXT: (if
+ ;; NO_PART-NEXT: (local.get $x)
+ ;; NO_PART-NEXT: (call $import)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_BOTH: (func $maybe-partial-or-full-1 (param $x i32)
+ ;; NO_BOTH-NEXT: (if
+ ;; NO_BOTH-NEXT: (local.get $x)
+ ;; NO_BOTH-NEXT: (call $import)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: )
+ (func $maybe-partial-or-full-1 (param $x i32)
+ ;; This function can be partially inlined, but after doing so we want to
+ ;; inline the remainder as well, so instead we fully inline it. When full
+ ;; inlining is disabled but partial inlining is enabled, we should only
+ ;; partially inline it.
+ (if
+ (local.get $x)
+ (call $import)
+ )
+ )
+
+ ;; NO_PART: (func $maybe-partial-or-full-2 (param $x i32)
+ ;; NO_PART-NEXT: (if
+ ;; NO_PART-NEXT: (local.get $x)
+ ;; NO_PART-NEXT: (return)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (nop)
+ ;; NO_PART-NEXT: (drop
+ ;; NO_PART-NEXT: (i32.const 0)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (drop
+ ;; NO_PART-NEXT: (i32.const 0)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (drop
+ ;; NO_PART-NEXT: (i32.const 0)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (drop
+ ;; NO_PART-NEXT: (i32.const 0)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (drop
+ ;; NO_PART-NEXT: (i32.const 0)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (drop
+ ;; NO_PART-NEXT: (i32.const 0)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (drop
+ ;; NO_PART-NEXT: (i32.const 0)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (drop
+ ;; NO_PART-NEXT: (i32.const 0)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_BOTH: (func $maybe-partial-or-full-2 (param $x i32)
+ ;; NO_BOTH-NEXT: (if
+ ;; NO_BOTH-NEXT: (local.get $x)
+ ;; NO_BOTH-NEXT: (return)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (nop)
+ ;; NO_BOTH-NEXT: (drop
+ ;; NO_BOTH-NEXT: (i32.const 0)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (drop
+ ;; NO_BOTH-NEXT: (i32.const 0)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (drop
+ ;; NO_BOTH-NEXT: (i32.const 0)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (drop
+ ;; NO_BOTH-NEXT: (i32.const 0)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (drop
+ ;; NO_BOTH-NEXT: (i32.const 0)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (drop
+ ;; NO_BOTH-NEXT: (i32.const 0)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (drop
+ ;; NO_BOTH-NEXT: (i32.const 0)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (drop
+ ;; NO_BOTH-NEXT: (i32.const 0)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: )
+ (func $maybe-partial-or-full-2 (param $x i32)
+ ;; As above, but for another form of partial inlining. Here we need to add
+ ;; some extra things to the function size for partial inlining to kick in.
+ (if
+ (local.get $x)
+ (return)
+ )
+ (nop)
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.const 0)
+ )
+ (drop
+ (i32.const 0)
+ )
+ )
+
+ ;; YES_ALL: (func $caller
+ ;; YES_ALL-NEXT: (local $0 i32)
+ ;; YES_ALL-NEXT: (local $1 i32)
+ ;; YES_ALL-NEXT: (local $2 i32)
+ ;; YES_ALL-NEXT: (local $3 i32)
+ ;; YES_ALL-NEXT: (block
+ ;; YES_ALL-NEXT: (block $__inlined_func$maybe-partial-or-full-1
+ ;; YES_ALL-NEXT: (local.set $0
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (if
+ ;; YES_ALL-NEXT: (local.get $0)
+ ;; YES_ALL-NEXT: (call $import)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (block
+ ;; YES_ALL-NEXT: (block $__inlined_func$maybe-partial-or-full-1$1
+ ;; YES_ALL-NEXT: (local.set $1
+ ;; YES_ALL-NEXT: (i32.const 1)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (if
+ ;; YES_ALL-NEXT: (local.get $1)
+ ;; YES_ALL-NEXT: (call $import)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (block
+ ;; YES_ALL-NEXT: (block $__inlined_func$maybe-partial-or-full-2$2
+ ;; YES_ALL-NEXT: (local.set $2
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (block
+ ;; YES_ALL-NEXT: (if
+ ;; YES_ALL-NEXT: (local.get $2)
+ ;; YES_ALL-NEXT: (br $__inlined_func$maybe-partial-or-full-2$2)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (nop)
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (block
+ ;; YES_ALL-NEXT: (block $__inlined_func$maybe-partial-or-full-2$3
+ ;; YES_ALL-NEXT: (local.set $3
+ ;; YES_ALL-NEXT: (i32.const 1)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (block
+ ;; YES_ALL-NEXT: (if
+ ;; YES_ALL-NEXT: (local.get $3)
+ ;; YES_ALL-NEXT: (br $__inlined_func$maybe-partial-or-full-2$3)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (nop)
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: (drop
+ ;; YES_ALL-NEXT: (i32.const 0)
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; YES_ALL-NEXT: )
+ ;; NO_PART: (func $caller
+ ;; NO_PART-NEXT: (call $maybe-partial-or-full-1
+ ;; NO_PART-NEXT: (i32.const 0)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (call $maybe-partial-or-full-1
+ ;; NO_PART-NEXT: (i32.const 1)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (call $maybe-partial-or-full-2
+ ;; NO_PART-NEXT: (i32.const 0)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: (call $maybe-partial-or-full-2
+ ;; NO_PART-NEXT: (i32.const 1)
+ ;; NO_PART-NEXT: )
+ ;; NO_PART-NEXT: )
+ ;; NO_FULL: (func $caller
+ ;; NO_FULL-NEXT: (local $0 i32)
+ ;; NO_FULL-NEXT: (local $1 i32)
+ ;; NO_FULL-NEXT: (local $2 i32)
+ ;; NO_FULL-NEXT: (local $3 i32)
+ ;; NO_FULL-NEXT: (local $4 i32)
+ ;; NO_FULL-NEXT: (local $5 i32)
+ ;; NO_FULL-NEXT: (local $6 i32)
+ ;; NO_FULL-NEXT: (local $7 i32)
+ ;; NO_FULL-NEXT: (block
+ ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-inlineable-B$maybe-partial-or-full-1
+ ;; NO_FULL-NEXT: (local.set $0
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (if
+ ;; NO_FULL-NEXT: (local.get $0)
+ ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-outlined-B$maybe-partial-or-full-1$4
+ ;; NO_FULL-NEXT: (local.set $4
+ ;; NO_FULL-NEXT: (local.get $0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (call $import)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (block
+ ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-inlineable-B$maybe-partial-or-full-1$1
+ ;; NO_FULL-NEXT: (local.set $1
+ ;; NO_FULL-NEXT: (i32.const 1)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (if
+ ;; NO_FULL-NEXT: (local.get $1)
+ ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-outlined-B$maybe-partial-or-full-1$5
+ ;; NO_FULL-NEXT: (local.set $5
+ ;; NO_FULL-NEXT: (local.get $1)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (call $import)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (block
+ ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-inlineable-A$maybe-partial-or-full-2$2
+ ;; NO_FULL-NEXT: (local.set $2
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (if
+ ;; NO_FULL-NEXT: (i32.eqz
+ ;; NO_FULL-NEXT: (local.get $2)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-outlined-A$maybe-partial-or-full-2$6
+ ;; NO_FULL-NEXT: (local.set $6
+ ;; NO_FULL-NEXT: (local.get $2)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (block
+ ;; NO_FULL-NEXT: (nop)
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (block
+ ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-inlineable-A$maybe-partial-or-full-2$3
+ ;; NO_FULL-NEXT: (local.set $3
+ ;; NO_FULL-NEXT: (i32.const 1)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (if
+ ;; NO_FULL-NEXT: (i32.eqz
+ ;; NO_FULL-NEXT: (local.get $3)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (block $__inlined_func$byn-split-outlined-A$maybe-partial-or-full-2$7
+ ;; NO_FULL-NEXT: (local.set $7
+ ;; NO_FULL-NEXT: (local.get $3)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (block
+ ;; NO_FULL-NEXT: (nop)
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: (drop
+ ;; NO_FULL-NEXT: (i32.const 0)
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_FULL-NEXT: )
+ ;; NO_BOTH: (func $caller
+ ;; NO_BOTH-NEXT: (call $maybe-partial-or-full-1
+ ;; NO_BOTH-NEXT: (i32.const 0)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (call $maybe-partial-or-full-1
+ ;; NO_BOTH-NEXT: (i32.const 1)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (call $maybe-partial-or-full-2
+ ;; NO_BOTH-NEXT: (i32.const 0)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: (call $maybe-partial-or-full-2
+ ;; NO_BOTH-NEXT: (i32.const 1)
+ ;; NO_BOTH-NEXT: )
+ ;; NO_BOTH-NEXT: )
+ (func $caller
+ ;; In YES_ALL we will fully inline all of these. In NO_FULL we will partially
+ ;; inline. In NO_PART and NO_BOTH we will not inline at all (in theory we
+ ;; could do full inlining when only partial inlining is disabled, but we only
+ ;; see that full inlining is possible as a result of partial inlining, so if
+ ;; partial is disabled we don't get there, and full inlining is not
+ ;; justified).
+ (call $maybe-partial-or-full-1
+ (i32.const 0)
+ )
+ (call $maybe-partial-or-full-1
+ (i32.const 1)
+ )
+ (call $maybe-partial-or-full-2
+ (i32.const 0)
+ )
+ (call $maybe-partial-or-full-2
+ (i32.const 1)
+ )
+ )
+)