Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge-similar-functions size optimization pass, which merges similar functions #4414

Merged
merged 17 commits into from
Mar 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 13 additions & 5 deletions src/ir/ExpressionAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,10 @@ struct Hasher {
std::map<Name, Index> internalNames;
ExpressionStack stack;

Hasher(Expression* curr, bool visitChildren) : visitChildren(visitChildren) {
Hasher(Expression* curr,
bool visitChildren,
ExpressionAnalyzer::ExprHasher custom)
: visitChildren(visitChildren) {
stack.push_back(curr);
// DELEGATE_CALLER_TARGET is a fake target used to denote delegating to
// the caller. Add it here to prevent the unknown name error.
Expand All @@ -287,7 +290,11 @@ struct Hasher {
// call_imports type, etc. The simplest thing is just to hash the
// type for all of them.
rehash(digest, curr->type.getID());
// Hash the contents of the expression.
// If the custom hasher handled this expr, then we have nothing to do.
if (custom(curr, digest)) {
continue;
}
// Hash the contents of the expression normally.
hashExpression(curr);
}
}
Expand Down Expand Up @@ -365,12 +372,13 @@ struct Hasher {

} // anonymous namespace

size_t ExpressionAnalyzer::hash(Expression* curr) {
return Hasher(curr, true).digest;
size_t ExpressionAnalyzer::flexibleHash(Expression* curr,
ExpressionAnalyzer::ExprHasher custom) {
return Hasher(curr, true, custom).digest;
}

size_t ExpressionAnalyzer::shallowHash(Expression* curr) {
return Hasher(curr, false).digest;
return Hasher(curr, false, ExpressionAnalyzer::nothingHasher).digest;
}

} // namespace wasm
26 changes: 21 additions & 5 deletions src/ir/hashed.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "ir/utils.h"
#include "support/hash.h"
#include "wasm.h"
#include <functional>

namespace wasm {

Expand All @@ -30,9 +31,14 @@ struct FunctionHasher : public WalkerPass<PostWalker<FunctionHasher>> {

struct Map : public std::map<Function*, size_t> {};

FunctionHasher(Map* output) : output(output) {}
FunctionHasher(Map* output, ExpressionAnalyzer::ExprHasher customHasher)
: output(output), customHasher(customHasher) {}
FunctionHasher(Map* output)
: output(output), customHasher(ExpressionAnalyzer::nothingHasher) {}

FunctionHasher* create() override { return new FunctionHasher(output); }
FunctionHasher* create() override {
return new FunctionHasher(output, customHasher);
}

static Map createMap(Module* module) {
Map hashes;
Expand All @@ -44,19 +50,29 @@ struct FunctionHasher : public WalkerPass<PostWalker<FunctionHasher>> {
return hashes;
}

void doWalkFunction(Function* func) { output->at(func) = hashFunction(func); }
void doWalkFunction(Function* func) {
output->at(func) = flexibleHashFunction(func, customHasher);
}

static size_t hashFunction(Function* func) {
static size_t
flexibleHashFunction(Function* func,
ExpressionAnalyzer::ExprHasher customHasher) {
auto digest = hash(func->type);
for (auto type : func->vars) {
rehash(digest, type.getID());
}
hash_combine(digest, ExpressionAnalyzer::hash(func->body));
hash_combine(digest,
ExpressionAnalyzer::flexibleHash(func->body, customHasher));
return digest;
}

static size_t hashFunction(Function* func) {
return flexibleHashFunction(func, ExpressionAnalyzer::nothingHasher);
}

private:
Map* output;
ExpressionAnalyzer::ExprHasher customHasher;
};

} // namespace wasm
Expand Down
10 changes: 9 additions & 1 deletion src/ir/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,17 @@ struct ExpressionAnalyzer {
return flexibleEqual(left, right, comparer);
}

// Returns true if the expression is handled by the hasher.
using ExprHasher = std::function<bool(Expression*, size_t&)>;
static bool nothingHasher(Expression*, size_t&) { return false; }

static size_t flexibleHash(Expression* curr, ExprHasher hasher);

// hash an expression, ignoring superficial details like specific internal
// names
static size_t hash(Expression* curr);
static size_t hash(Expression* curr) {
return flexibleHash(curr, nothingHasher);
}

// hash an expression, ignoring child nodes.
static size_t shallowHash(Expression* curr);
Expand Down
1 change: 1 addition & 0 deletions src/passes/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ set(passes_SOURCES
Memory64Lowering.cpp
MemoryPacking.cpp
MergeBlocks.cpp
MergeSimilarFunctions.cpp
MergeLocals.cpp
Metrics.cpp
MinifyImportsAndExports.cpp
Expand Down