-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Update after Binaryen change to inline all single-use functions #13744
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Nice! |
Awesome! I think I argued for more aggressive inlining by default in the past :) It is an interesting question who is responsible for things like start-up times, and whether the tools side should be in the business of protecting engines against their own slowness in any current implementation. Engines may eventually have to deal with these as other toolchains produce these, and they're a moving target. I'd definitely say that focusing on speed (which is also abstract to some extent) & size is more important. |
Nice! I agree it's better to do this. By the way, how can we be sure if a function is single use, in the presence of indirect calls? Do we exclude calls that can be called indirectly from multiple places? |
This looks nice, and I agree with what folks have said here so far. Regarding indirect calls, I think the answer is that if a function is address-taken (i.e. if it's in the table) then it can't be removed entirely, so it probably shouldn't be inlined into a direct caller (since that would be a duplication). Or maybe you could say that a direct caller is one use, and presence in the table is another use, so if we had another heuristic that said inlining/duplicating was good even for some multiple-use functions, it could still apply there. |
Yes, the pass considers an appearance in the table as a global use (which can't be inlined into, and prevents inlining as a single-use function). |
Agreed that it would be very beneficial to have this on by default. I would recommend having it as a flag that can be disabled if explicitly desired. |
I strongly support this. The current V8 policy is to allow more compile time in the optimizing compiler, and this will help us produce better code. |
This implements emscripten-core/emscripten#13744 Inlining functions with a single use allows us to remove the function afterward. That looks highly beneficial, shrinking every single benchmark in emscripten's benchmark suite, by an average of 2% on the macrobenchmarks and 3.5% on all of them. Speed also improves, although mostly on the microbenchmarks so that might be less realistic. There may be a slight downside to startup time due to emitting larger functions, but given the baseline compilers in VMs these days it seems worth it, as the delay would be just to get to the upper tier. On the benchmark suite the risk seems low. See more details in the PR above.
That can currently be done with |
To allow the binaryen inlining improvement to roll in. See WebAssembly/binaryen#3730 and #13744
… traces (#13792) To allow the binaryen inlining improvement to roll in. See WebAssembly/binaryen#3730 and #13744
The binaryen change landed, and this should be ready to go. It must wait for the binaryen change to roll however. |
Investigating the tuning of the binaryen inliner with @manoskouk , it looks like always inlining single-use functions is beneficial. In that case we can delete the function after inlining, so the code is "moved". Binaryen's default is to only inline fairly small functions in that case, but the heuristic is too conservative it seems. This PR shows what happens if we always inline such functions.
Positive findings:
Negative findings:
Overall I think we should make this change. The positives are very strong, better than I expected. It would also let us deprecate and eventually remove a flag from Binaryen (unless we decide it's worth keeping?)
Thoughts?
cc @dschuff @sbc100 @aheejin @tlively @aardappel @juj @manoskouk @jakobkummerow