summaryrefslogtreecommitdiff
path: root/src/ir
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-09-16 20:03:37 -0700
committerGitHub <noreply@github.com>2021-09-17 03:03:37 +0000
commiteb83c4257976f9536b98df43e8f2242a102b3ce4 (patch)
treeb0ee4c4b23744c52723eb66de414fc3e18ac695c /src/ir
parent8e8bce1b59a8d60a35e21798c6aec95e3dcade6b (diff)
downloadbinaryen-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.h12
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) {