summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2020-04-10 01:01:23 -0400
committerGitHub <noreply@github.com>2020-04-09 22:01:23 -0700
commit6a51af5d858b6d3378749d17065c44cf50b62a26 (patch)
tree20dfbc05715519ff75355143c851b6c2e5fb3d81 /src
parent1b56c2b341e838656adca9a7101d824ed757d6ad (diff)
downloadbinaryen-6a51af5d858b6d3378749d17065c44cf50b62a26.tar.gz
binaryen-6a51af5d858b6d3378749d17065c44cf50b62a26.tar.bz2
binaryen-6a51af5d858b6d3378749d17065c44cf50b62a26.zip
Remove writes to globals that are never written to (#2741)
Since the global is never read, we know that any write operation will be unobservable.
Diffstat (limited to 'src')
-rw-r--r--src/passes/SimplifyGlobals.cpp39
-rw-r--r--src/passes/pass.cpp1
2 files changed, 40 insertions, 0 deletions
diff --git a/src/passes/SimplifyGlobals.cpp b/src/passes/SimplifyGlobals.cpp
index 5fa1686fc..71aafa491 100644
--- a/src/passes/SimplifyGlobals.cpp
+++ b/src/passes/SimplifyGlobals.cpp
@@ -51,6 +51,7 @@ struct GlobalInfo {
bool imported = false;
bool exported = false;
std::atomic<bool> written;
+ std::atomic<bool> read;
};
using GlobalInfoMap = std::map<Name, GlobalInfo>;
@@ -64,6 +65,8 @@ struct GlobalUseScanner : public WalkerPass<PostWalker<GlobalUseScanner>> {
void visitGlobalSet(GlobalSet* curr) { (*infos)[curr->name].written = true; }
+ void visitGlobalGet(GlobalGet* curr) { (*infos)[curr->name].read = true; }
+
private:
GlobalInfoMap* infos;
};
@@ -163,6 +166,23 @@ private:
std::map<Name, Literals> currConstantGlobals;
};
+struct GlobalSetRemover : public WalkerPass<PostWalker<GlobalSetRemover>> {
+ GlobalSetRemover(NameSet* toRemove) : toRemove(toRemove) {}
+
+ bool isFunctionParallel() override { return true; }
+
+ GlobalSetRemover* create() override { return new GlobalSetRemover(toRemove); }
+
+ void visitGlobalSet(GlobalSet* curr) {
+ if (toRemove->count(curr->name) != 0) {
+ ExpressionManipulator::nop(curr);
+ }
+ }
+
+private:
+ NameSet* toRemove;
+};
+
} // anonymous namespace
struct SimplifyGlobals : public Pass {
@@ -180,6 +200,8 @@ struct SimplifyGlobals : public Pass {
analyze();
+ removeWritesToUnreadGlobals();
+
preferEarlierImports();
propagateConstantsToGlobals();
@@ -211,6 +233,23 @@ struct SimplifyGlobals : public Pass {
}
}
+ void removeWritesToUnreadGlobals() {
+ // Globals that are not exports and not read from can be eliminated
+ // (even if they are written to).
+ NameSet unreadGlobals;
+ for (auto& global : module->globals) {
+ auto& info = map[global->name];
+ if (!info.imported && !info.exported && !info.read) {
+ unreadGlobals.insert(global->name);
+ // We can now mark this global as immutable, and un-written, since we
+ // are about to remove all the `.set` operations on it.
+ global->mutable_ = false;
+ info.written = false;
+ }
+ }
+ GlobalSetRemover(&unreadGlobals).run(runner, module);
+ }
+
void preferEarlierImports() {
// Optimize uses of immutable globals, prefer the earlier import when
// there is a copy.
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index 733b61467..4da870ae9 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -483,6 +483,7 @@ void PassRunner::addDefaultGlobalOptimizationPostPasses() {
} else {
add("simplify-globals");
}
+ add("vacuum"); // simplify-globals can generate extra nops
add("remove-unused-module-elements");
// may allow more inlining/dae/etc., need --converge for that
add("directize");