Skip to content

Commit 2093823

Browse files
authored
wasm-reduce: Try to remove functions from a random place (#4612)
Previously we'd only try to remove functions from index 0, so we missed some opportunities. With this change we still go through all the functions if things go well, but we start from a deterministic random location in the vector.
1 parent 23a1a79 commit 2093823

File tree

1 file changed

+32
-7
lines changed

1 file changed

+32
-7
lines changed

src/tools/wasm-reduce.cpp

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "support/colors.h"
3636
#include "support/command-line.h"
3737
#include "support/file.h"
38+
#include "support/hash.h"
3839
#include "support/path.h"
3940
#include "support/timing.h"
4041
#include "tool-options.h"
@@ -397,10 +398,21 @@ struct Reducer
397398
return out == expected;
398399
}
399400

401+
size_t decisionCounter = 0;
402+
400403
bool shouldTryToReduce(size_t bonus = 1) {
401-
static size_t counter = 0;
402-
counter += bonus;
403-
return (counter % factor) <= bonus;
404+
assert(bonus > 0);
405+
// Increment to avoid returning the same result each time.
406+
decisionCounter += bonus;
407+
return (decisionCounter % factor) <= bonus;
408+
}
409+
410+
// Returns a random number in the range [0, max). This is deterministic given
411+
// all the previous work done in the reducer.
412+
size_t deterministicRandom(size_t max) {
413+
assert(max > 0);
414+
hash_combine(decisionCounter, max);
415+
return decisionCounter % max;
404416
}
405417

406418
bool isOkReplacement(Expression* with) {
@@ -869,17 +881,26 @@ struct Reducer
869881
// amount of reduction that justifies doing even more.
870882
bool reduceFunctions() {
871883
// try to remove functions
872-
std::cerr << "| try to remove functions\n";
873884
std::vector<Name> functionNames;
874885
for (auto& func : module->functions) {
875886
functionNames.push_back(func->name);
876887
}
888+
auto numFuncs = functionNames.size();
889+
if (numFuncs == 0) {
890+
return false;
891+
}
877892
size_t skip = 1;
878893
size_t maxSkip = 1;
879894
// If we just removed some functions in the previous iteration, keep trying
880895
// to remove more as this is one of the most efficient ways to reduce.
881896
bool justReduced = true;
882-
for (size_t i = 0; i < functionNames.size(); i++) {
897+
// Start from a new place each time.
898+
size_t base = deterministicRandom(numFuncs);
899+
std::cerr << "| try to remove functions (base: " << base
900+
<< ", decisionCounter: " << decisionCounter << ", numFuncs "
901+
<< numFuncs << ")\n";
902+
for (size_t x = 0; x < functionNames.size(); x++) {
903+
size_t i = (base + x) % numFuncs;
883904
if (!justReduced &&
884905
functionsWeTriedToRemove.count(functionNames[i]) == 1 &&
885906
!shouldTryToReduce(std::max((factor / 5) + 1, 20000))) {
@@ -897,18 +918,22 @@ struct Reducer
897918
if (names.size() == 0) {
898919
continue;
899920
}
921+
std::cerr << "| trying at i=" << i << " of size " << names.size()
922+
<< "\n";
900923
// Try to remove functions and/or empty them. Note that
901924
// tryToRemoveFunctions() will reload the module if it fails, which means
902925
// function names may change - for that reason, run it second.
903926
justReduced = tryToEmptyFunctions(names) || tryToRemoveFunctions(names);
904927
if (justReduced) {
905928
noteReduction(names.size());
906-
i += skip;
929+
// Subtract 1 since the loop increments us anyhow by one: we want to
930+
// skip over the skipped functions, and not any more.
931+
x += skip - 1;
907932
skip = std::min(size_t(factor), 2 * skip);
908933
maxSkip = std::max(skip, maxSkip);
909934
} else {
910935
skip = std::max(skip / 2, size_t(1)); // or 1?
911-
i += factor / 100;
936+
x += factor / 100;
912937
}
913938
}
914939
// If maxSkip is 1 then we never reduced at all. If it is 2 then we did

0 commit comments

Comments
 (0)