Skip to content

Commit 60bd610

Browse files
authored
[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.
1 parent 692e55c commit 60bd610

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

src/wasm/wasm-stack-opts.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
// Operations on Stack IR.
1919
//
2020

21+
#include "ir/branch-utils.h"
2122
#include "ir/iteration.h"
2223
#include "ir/local-graph.h"
2324
#include "pass.h"
@@ -269,17 +270,26 @@ void StackIROptimizer::local2Stack() {
269270
}
270271
}
271272

272-
// There may be unnecessary blocks we can remove: blocks
273-
// without branches to them are always ok to remove.
274-
// TODO: a branch to a block in an if body can become
275-
// a branch to that if body
273+
// There may be unnecessary blocks we can remove: blocks without arriving
274+
// branches are always ok to remove.
275+
// TODO: A branch to a block in an if body can become a branch to that if body.
276276
void StackIROptimizer::removeUnneededBlocks() {
277+
// First, find all branch targets.
278+
std::unordered_set<Name> targets;
279+
for (auto*& inst : insts) {
280+
if (inst) {
281+
BranchUtils::operateOnScopeNameUses(
282+
inst->origin, [&](Name& name) { targets.insert(name); });
283+
}
284+
}
285+
286+
// Remove untargeted blocks.
277287
for (auto*& inst : insts) {
278288
if (!inst) {
279289
continue;
280290
}
281291
if (auto* block = inst->origin->dynCast<Block>()) {
282-
if (!BranchUtils::BranchSeeker::has(block, block->name)) {
292+
if (!block->name.is() || !targets.count(block->name)) {
283293
// TODO optimize, maybe run remove-unused-names
284294
inst = nullptr;
285295
}

0 commit comments

Comments
 (0)