diff options
author | Alon Zakai <alonzakai@gmail.com> | 2018-01-10 11:34:53 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-10 11:34:53 -0800 |
commit | 623e42aa7be8aa030093b204491d94f3c297d312 (patch) | |
tree | 05158ff7c3ef2856345c1650192283ed737f91fd /src/passes/RemoveUnusedModuleElements.cpp | |
parent | 8f90b655201e4cd77196a0b90ea4f398ecfe2c56 (diff) | |
download | binaryen-623e42aa7be8aa030093b204491d94f3c297d312.tar.gz binaryen-623e42aa7be8aa030093b204491d94f3c297d312.tar.bz2 binaryen-623e42aa7be8aa030093b204491d94f3c297d312.zip |
Optimize out memory and table when possible (#1352)
We can remove the memory/table (itself, or an import if imported) if they are not used. This is pretty minor on a large wasm file, but when reading small wasts it's very noticeable to have an unused memory and table all the time.
Diffstat (limited to 'src/passes/RemoveUnusedModuleElements.cpp')
-rw-r--r-- | src/passes/RemoveUnusedModuleElements.cpp | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/passes/RemoveUnusedModuleElements.cpp b/src/passes/RemoveUnusedModuleElements.cpp index 8bf2f9c9a..13caaccc9 100644 --- a/src/passes/RemoveUnusedModuleElements.cpp +++ b/src/passes/RemoveUnusedModuleElements.cpp @@ -43,6 +43,8 @@ struct ReachabilityAnalyzer : public PostWalker<ReachabilityAnalyzer> { Module* module; std::vector<ModuleElement> queue; std::set<ModuleElement> reachable; + bool usesMemory = false; + bool usesTable = false; ReachabilityAnalyzer(Module* module, const std::vector<ModuleElement>& roots) : module(module) { queue = roots; @@ -86,6 +88,9 @@ struct ReachabilityAnalyzer : public PostWalker<ReachabilityAnalyzer> { queue.emplace_back(ModuleElementKind::Function, curr->target); } } + void visitCallIndirect(CallIndirect* curr) { + usesTable = true; + } void visitGetGlobal(GetGlobal* curr) { if (reachable.count(ModuleElement(ModuleElementKind::Global, curr->name)) == 0) { @@ -97,6 +102,30 @@ struct ReachabilityAnalyzer : public PostWalker<ReachabilityAnalyzer> { queue.emplace_back(ModuleElementKind::Global, curr->name); } } + + void visitLoad(Load* curr) { + usesMemory = true; + } + void visitStore(Store* curr) { + usesMemory = true; + } + void visitAtomicCmpxchg(AtomicCmpxchg* curr) { + usesMemory = true; + } + void visitAtomicRMW(AtomicRMW* curr) { + usesMemory = true; + } + void visitAtomicWait(AtomicWait* curr) { + usesMemory = true; + } + void visitAtomicWake(AtomicWake* curr) { + usesMemory = true; + } + void visitHost(Host* curr) { + if (curr->op == CurrentMemory || curr->op == GrowMemory) { + usesMemory = true; + } + } }; // Finds function type usage @@ -136,11 +165,17 @@ struct RemoveUnusedModuleElements : public Pass { roots.emplace_back(ModuleElementKind::Function, module->start); } // Exports are roots. + bool exportsMemory = false; + bool exportsTable = false; for (auto& curr : module->exports) { if (curr->kind == ExternalKind::Function) { roots.emplace_back(ModuleElementKind::Function, curr->value); } else if (curr->kind == ExternalKind::Global) { roots.emplace_back(ModuleElementKind::Global, curr->value); + } else if (curr->kind == ExternalKind::Memory) { + exportsMemory = true; + } else if (curr->kind == ExternalKind::Table) { + exportsTable = true; } } // For now, all functions that can be called indirectly are marked as roots. @@ -176,6 +211,28 @@ struct RemoveUnusedModuleElements : public Pass { }), v.end()); } module->updateMaps(); + // Handle the memory and table + if (!exportsMemory && !analyzer.usesMemory && module->memory.segments.empty()) { + module->memory.exists = false; + module->memory.imported = false; + module->memory.initial = 0; + module->memory.max = 0; + removeImport(ExternalKind::Memory, module); + } + if (!exportsTable && !analyzer.usesTable && module->table.segments.empty()) { + module->table.exists = false; + module->table.imported = false; + module->table.initial = 0; + module->table.max = 0; + removeImport(ExternalKind::Table, module); + } + } + + void removeImport(ExternalKind kind, Module* module) { + auto& v = module->imports; + v.erase(std::remove_if(v.begin(), v.end(), [&](const std::unique_ptr<Import>& curr) { + return curr->kind == kind; + }), v.end()); } void optimizeFunctionTypes(Module* module) { |