Skip to content

Commit 43902cc

Browse files
committed
Make MaxCombinedBinarySize configurable
Use case: I want to avoid generating "huge" (eg. 50KB) functions, which can involve certain kind of text relocations in aot-compiled binaries for my target.
1 parent 3b4856e commit 43902cc

5 files changed

Lines changed: 43 additions & 13 deletions

File tree

src/binaryen-c.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5754,6 +5754,14 @@ void BinaryenSetFlexibleInlineMaxSize(BinaryenIndex size) {
57545754
globalPassOptions.inlining.flexibleInlineMaxSize = size;
57555755
}
57565756

5757+
BinaryenIndex BinaryenGetMaxCombinedBinarySize(void) {
5758+
return globalPassOptions.inlining.maxCombinedBinarySize;
5759+
}
5760+
5761+
void BinaryenSetMaxCombinedBinarySize(BinaryenIndex size) {
5762+
globalPassOptions.inlining.maxCombinedBinarySize = size;
5763+
}
5764+
57575765
BinaryenIndex BinaryenGetOneCallerInlineMaxSize(void) {
57585766
return globalPassOptions.inlining.oneCallerInlineMaxSize;
57595767
}

src/binaryen-c.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3148,6 +3148,14 @@ BINARYEN_API BinaryenIndex BinaryenGetFlexibleInlineMaxSize(void);
31483148
// Applies to all modules, globally.
31493149
BINARYEN_API void BinaryenSetFlexibleInlineMaxSize(BinaryenIndex size);
31503150

3151+
// Gets the limit for the combined size of the code after inlining.
3152+
// Applies to all modules, globally.
3153+
BINARYEN_API BinaryenIndex BinaryenGetMaxCombinedBinarySize(void);
3154+
3155+
// Sets the limit for the combined size of the code after inlining.
3156+
// Applies to all modules, globally.
3157+
BINARYEN_API void BinaryenSetMaxCombinedBinarySize(BinaryenIndex size);
3158+
31513159
// Gets the function size which we inline when there is only one caller.
31523160
// Applies to all modules, globally.
31533161
BINARYEN_API BinaryenIndex BinaryenGetOneCallerInlineMaxSize(void);

src/pass.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,17 @@ struct InliningOptions {
8989
// This is checked after alwaysInlineMaxSize and oneCallerInlineMaxSize, but
9090
// the order normally won't matter.
9191
Index flexibleInlineMaxSize = 20;
92+
// The limit for the combined size of the code after inlining.
93+
// We have an absolute limit in order to avoid extremely-large sizes after
94+
// inlining, as they may hit limits in VMs and/or slow down startup
95+
// (measurements there indicate something like ~1 second to optimize a 100K
96+
// function). See e.g.
97+
// https://github.com/WebAssembly/binaryen/pull/3730#issuecomment-867939138
98+
// https://github.com/emscripten-core/emscripten/issues/13899#issuecomment-825073344
99+
// The limit is arbitrary, but based on the links above. It is a very high
100+
// value that should appear very rarely in practice (for example, it does
101+
// not occur on the Emscripten benchmark suite of real-world codebases).
102+
Index maxCombinedBinarySize = 400 * 1024;
92103
// Loops usually mean the function does heavy work, so the call overhead
93104
// is not significant and we do not inline such functions by default.
94105
bool allowFunctionsWithLoops = false;

src/passes/Inlining.cpp

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,7 +1398,8 @@ struct Inlining : public Pass {
13981398
continue;
13991399
}
14001400
Name inlinedName = inlinedFunction->name;
1401-
if (!isUnderSizeLimit(func->name, inlinedName)) {
1401+
if (!isUnderSizeLimit(
1402+
func->name, inlinedName, getPassRunner()->options)) {
14021403
continue;
14031404
}
14041405

@@ -1501,21 +1502,12 @@ struct Inlining : public Pass {
15011502
}
15021503

15031504
// Checks if the combined size of the code after inlining is under the
1504-
// absolute size limit. We have an absolute limit in order to avoid
1505-
// extremely-large sizes after inlining, as they may hit limits in VMs and/or
1506-
// slow down startup (measurements there indicate something like ~1 second to
1507-
// optimize a 100K function). See e.g.
1508-
// https://github.com/WebAssembly/binaryen/pull/3730#issuecomment-867939138
1509-
// https://github.com/emscripten-core/emscripten/issues/13899#issuecomment-825073344
1510-
bool isUnderSizeLimit(Name target, Name source) {
1505+
// absolute size limit.
1506+
bool isUnderSizeLimit(Name target, Name source, PassOptions& options) {
15111507
// Estimate the combined binary size from the number of instructions.
15121508
auto combinedSize = infos[target].size + infos[source].size;
15131509
auto estimatedBinarySize = Measurer::BytesPerExpr * combinedSize;
1514-
// The limit is arbitrary, but based on the links above. It is a very high
1515-
// value that should appear very rarely in practice (for example, it does
1516-
// not occur on the Emscripten benchmark suite of real-world codebases).
1517-
const Index MaxCombinedBinarySize = 400 * 1024;
1518-
return estimatedBinarySize < MaxCombinedBinarySize;
1510+
return estimatedBinarySize < options.inlining.maxCombinedBinarySize;
15191511
}
15201512
};
15211513

src/tools/optimization-options.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,17 @@ struct OptimizationOptions : public ToolOptions {
246246
passOptions.inlining.oneCallerInlineMaxSize =
247247
static_cast<Index>(atoi(argument.c_str()));
248248
})
249+
.add("--inline-max-combined-binary-size",
250+
"-imcbs",
251+
"Max size of combined functions after inlining. "
252+
"Default: " +
253+
std::to_string(InliningOptions().maxCombinedBinarySize),
254+
OptimizationOptionsCategory,
255+
Options::Arguments::One,
256+
[this](Options* o, const std::string& argument) {
257+
passOptions.inlining.maxCombinedBinarySize =
258+
static_cast<Index>(atoi(argument.c_str()));
259+
})
249260
.add("--inline-functions-with-loops",
250261
"-ifwl",
251262
"Allow inlining functions with loops",

0 commit comments

Comments
 (0)