diff options
Diffstat (limited to 'src/passes/Inlining.cpp')
-rw-r--r-- | src/passes/Inlining.cpp | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp index 1a84918bb..7c51e78cb 100644 --- a/src/passes/Inlining.cpp +++ b/src/passes/Inlining.cpp @@ -420,6 +420,9 @@ struct Inlining : public Pass { continue; } Name inlinedName = inlinedFunction->name; + if (!isUnderSizeLimit(func->name, inlinedName)) { + continue; + } #ifdef INLINING_DEBUG std::cout << "inline " << inlinedName << " into " << func->name << '\n'; #endif @@ -446,6 +449,24 @@ struct Inlining : public Pass { // return whether we did any work return inlinedUses.size() > 0; } + + // 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 + // slow down startup (measurements there indicate something like ~1 second to + // optimize a 100K function). See e.g. + // https://github.com/WebAssembly/binaryen/pull/3730#issuecomment-867939138 + // https://github.com/emscripten-core/emscripten/issues/13899#issuecomment-825073344 + bool isUnderSizeLimit(Name target, Name source) { + // Estimate the combined binary size from the number of instructions. + auto combinedSize = infos[target].size + infos[source].size; + auto estimatedBinarySize = Measurer::BytesPerExpr * combinedSize; + // The limit is arbitrary, but based on the links above. It is a very high + // value that should appear very rarely in practice (for example, it does + // not occur on the Emscripten benchmark suite of real-world codebases). + const Index MaxCombinedBinarySize = 400 * 1024; + return estimatedBinarySize < MaxCombinedBinarySize; + } }; Pass* createInliningPass() { return new Inlining(); } |