diff options
author | Alon Zakai <azakai@google.com> | 2021-09-16 20:03:37 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-17 03:03:37 +0000 |
commit | eb83c4257976f9536b98df43e8f2242a102b3ce4 (patch) | |
tree | b0ee4c4b23744c52723eb66de414fc3e18ac695c /src/ir | |
parent | 8e8bce1b59a8d60a35e21798c6aec95e3dcade6b (diff) | |
download | binaryen-eb83c4257976f9536b98df43e8f2242a102b3ce4.tar.gz binaryen-eb83c4257976f9536b98df43e8f2242a102b3ce4.tar.bz2 binaryen-eb83c4257976f9536b98df43e8f2242a102b3ce4.zip |
Partial inlining via function splitting (#4152)
This PR helps with functions like this:
function foo(x) {
if (x) {
..
lots of work here
..
}
}
If "lots of work" is large enough, then we won't inline such a
function. However, we may end up calling into the function
only to get a false on that if and immediately exit. So it is useful
to partially inline this function, basically by creating a split
of it into a condition part that is inlineable
function foo$inlineable(x) {
if (x) {
foo$outlined();
}
}
and an outlined part that is not inlineable:
function foo$outlined(x) {
..
lots of work here
..
}
We can then inline the inlineable part. That means that a call
like
foo(param);
turns into
if (param) {
foo$outlined();
}
In other words, we end up replacing a call and then a check with
a check and then a call. Any time that the condition is false, this
will be a speedup.
The cost here is increased size, as we duplicate the condition
into the callsites. For that reason, only do this when heavily
optimizing for size.
This is a 10% speedup on j2cl. This helps two types of functions
there: Java class inits, which often look like "have I been
initialized before? if not, do all this work", and also assertion
methods which look like "if the input is null, throw an
exception".
Diffstat (limited to 'src/ir')
-rw-r--r-- | src/ir/module-utils.h | 12 |
1 files changed, 7 insertions, 5 deletions
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) { |