summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-08-21 16:12:42 -0700
committerGitHub <noreply@github.com>2024-08-21 16:12:42 -0700
commit60bd610acaa91cab538497342eb06e3b50d2fac9 (patch)
treecc26e482aeaf5f0ac5b5a8ab03733ee809f5d88a /src
parent692e55c14bd3055b1aae49681bb8e62c757c678d (diff)
downloadbinaryen-60bd610acaa91cab538497342eb06e3b50d2fac9.tar.gz
binaryen-60bd610acaa91cab538497342eb06e3b50d2fac9.tar.bz2
binaryen-60bd610acaa91cab538497342eb06e3b50d2fac9.zip
[NFC] Avoid quadratic time in StackIROptimizer::removeUnneededBlocks() (#6859)
This is in quite ancient code, so it's a long-standing issue, but it got worse when we enabled StackIR in more situations (#6568), which made it more noticeable, I think. For example, testing on test_biggerswitch in Emscripten, the LLVM part is pretty slow too so the Binaryen slowdown didn't stand out hugely, but just doing wasm-opt --optimize-level=2 input.wasm -o output.wasm (that is, do no work, but set the optimize level to 2 so that StackIR opts are run) used to take 28 seconds (!). With this PR that goes down to less than 1.
Diffstat (limited to 'src')
-rw-r--r--src/wasm/wasm-stack-opts.cpp20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/wasm/wasm-stack-opts.cpp b/src/wasm/wasm-stack-opts.cpp
index 5e18cf26f..cf4c094b5 100644
--- a/src/wasm/wasm-stack-opts.cpp
+++ b/src/wasm/wasm-stack-opts.cpp
@@ -18,6 +18,7 @@
// Operations on Stack IR.
//
+#include "ir/branch-utils.h"
#include "ir/iteration.h"
#include "ir/local-graph.h"
#include "pass.h"
@@ -269,17 +270,26 @@ void StackIROptimizer::local2Stack() {
}
}
-// There may be unnecessary blocks we can remove: blocks
-// without branches to them are always ok to remove.
-// TODO: a branch to a block in an if body can become
-// a branch to that if body
+// There may be unnecessary blocks we can remove: blocks without arriving
+// branches are always ok to remove.
+// TODO: A branch to a block in an if body can become a branch to that if body.
void StackIROptimizer::removeUnneededBlocks() {
+ // First, find all branch targets.
+ std::unordered_set<Name> targets;
+ for (auto*& inst : insts) {
+ if (inst) {
+ BranchUtils::operateOnScopeNameUses(
+ inst->origin, [&](Name& name) { targets.insert(name); });
+ }
+ }
+
+ // Remove untargeted blocks.
for (auto*& inst : insts) {
if (!inst) {
continue;
}
if (auto* block = inst->origin->dynCast<Block>()) {
- if (!BranchUtils::BranchSeeker::has(block, block->name)) {
+ if (!block->name.is() || !targets.count(block->name)) {
// TODO optimize, maybe run remove-unused-names
inst = nullptr;
}