diff options
author | Alon Zakai <azakai@google.com> | 2024-09-03 13:53:36 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-03 13:53:36 -0700 |
commit | 48d4c55116728823fbdbc1dd13f8f8916ac0b0af (patch) | |
tree | 23471599f6e53ff076428f5743adb77bcae32824 /src/passes/param-utils.cpp | |
parent | 8125f7ab5124bbe1cd18b2d8be6a3877ba97acdb (diff) | |
download | binaryen-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.cpp | 14 |
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, |