summaryrefslogtreecommitdiff
path: root/src/passes/param-utils.cpp
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-09-03 13:53:36 -0700
committerGitHub <noreply@github.com>2024-09-03 13:53:36 -0700
commit48d4c55116728823fbdbc1dd13f8f8916ac0b0af (patch)
tree23471599f6e53ff076428f5743adb77bcae32824 /src/passes/param-utils.cpp
parent8125f7ab5124bbe1cd18b2d8be6a3877ba97acdb (diff)
downloadbinaryen-48d4c55116728823fbdbc1dd13f8f8916ac0b0af.tar.gz
binaryen-48d4c55116728823fbdbc1dd13f8f8916ac0b0af.tar.bz2
binaryen-48d4c55116728823fbdbc1dd13f8f8916ac0b0af.zip
[NFC] Avoid repeated work in DeadArgumentElimination scanning (#6869)
This pass may do multiple iterations, and before this PR it scanned the entire module each time. That is simpler than tracking stale data, but it can be quite slow. This PR adds staleness tracking, which makes it over 3x faster (and this can be one of our slowest passes in some cases, so this is significant). To achieve this: * Add a staleness marker on function info. * Rewrite how we track unseen calls. Previously we used atomics in a clever way, * now we just accumulate the data in a simple way (easier for staleness tracking). * Add staleness invalidation in the proper places. * Add a param to localizeCallsTo to allow us to learn when a function is changed. This kind of staleness analysis is usually not worthwhile, but given the 3x plus speedup it seems justified. I fuzzed it directly, and also any staleness bug can lead to validation errors, so normal fuzzing also gives us good coverage here.
Diffstat (limited to 'src/passes/param-utils.cpp')
-rw-r--r--src/passes/param-utils.cpp14
1 files changed, 9 insertions, 5 deletions
diff --git a/src/passes/param-utils.cpp b/src/passes/param-utils.cpp
index f54f91bd9..a600e1928 100644
--- a/src/passes/param-utils.cpp
+++ b/src/passes/param-utils.cpp
@@ -286,18 +286,21 @@ SortedVector applyConstantValues(const std::vector<Function*>& funcs,
void localizeCallsTo(const std::unordered_set<Name>& callTargets,
Module& wasm,
- PassRunner* runner) {
+ PassRunner* runner,
+ std::function<void(Function*)> onChange) {
struct LocalizerPass : public WalkerPass<PostWalker<LocalizerPass>> {
bool isFunctionParallel() override { return true; }
std::unique_ptr<Pass> create() override {
- return std::make_unique<LocalizerPass>(callTargets);
+ return std::make_unique<LocalizerPass>(callTargets, onChange);
}
const std::unordered_set<Name>& callTargets;
+ std::function<void(Function*)> onChange;
- LocalizerPass(const std::unordered_set<Name>& callTargets)
- : callTargets(callTargets) {}
+ LocalizerPass(const std::unordered_set<Name>& callTargets,
+ std::function<void(Function*)> onChange)
+ : callTargets(callTargets), onChange(onChange) {}
void visitCall(Call* curr) {
if (!callTargets.count(curr->target)) {
@@ -310,6 +313,7 @@ void localizeCallsTo(const std::unordered_set<Name>& callTargets,
if (replacement != curr) {
replaceCurrent(replacement);
optimized = true;
+ onChange(getFunction());
}
}
@@ -323,7 +327,7 @@ void localizeCallsTo(const std::unordered_set<Name>& callTargets,
}
};
- LocalizerPass(callTargets).run(runner, &wasm);
+ LocalizerPass(callTargets, onChange).run(runner, &wasm);
}
void localizeCallsTo(const std::unordered_set<HeapType>& callTargets,