diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/module-utils.cpp | 40 | ||||
-rw-r--r-- | src/passes/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/passes/RemoveUnusedTypes.cpp | 48 | ||||
-rw-r--r-- | src/passes/pass.cpp | 4 | ||||
-rw-r--r-- | src/passes/passes.h | 1 |
5 files changed, 84 insertions, 10 deletions
diff --git a/src/ir/module-utils.cpp b/src/ir/module-utils.cpp index f2c90dcfd..f3d9201b7 100644 --- a/src/ir/module-utils.cpp +++ b/src/ir/module-utils.cpp @@ -84,7 +84,9 @@ struct CodeScanner // not written in the binary format, so it doesn't need to be counted, but // it does need to be taken into account in the IR (this may be the only // place this type appears in the entire binary, and we must scan all - // types as the analyses that use us depend on that). + // types as the analyses that use us depend on that). TODO: This is kind + // of a hack, so it would be nice to remove. If we could remove it, we + // could also remove some of the pruning logic in getHeapTypeCounts below. counts.include(get->type); } else if (auto* set = curr->dynCast<StructSet>()) { counts.note(set->ref->type); @@ -105,7 +107,10 @@ struct CodeScanner } }; -Counts getHeapTypeCounts(Module& wasm) { +// Count the number of times each heap type that would appear in the binary is +// referenced. If `prune`, exclude types that are never referenced, even though +// a binary would be invalid without them. +Counts getHeapTypeCounts(Module& wasm, bool prune = false) { // Collect module-level info. Counts counts; CodeScanner(wasm, counts).walkModuleCode(&wasm); @@ -141,6 +146,19 @@ Counts getHeapTypeCounts(Module& wasm) { } } + if (prune) { + // Remove types that are not actually used. + auto it = counts.begin(); + while (it != counts.end()) { + if (it->second == 0) { + auto deleted = it++; + counts.erase(deleted); + } else { + ++it; + } + } + } + // Recursively traverse each reference type, which may have a child type that // is itself a reference type. This reflects an appearance in the binary // format that is in the type section itself. As we do this we may find more @@ -178,12 +196,14 @@ Counts getHeapTypeCounts(Module& wasm) { } // Make sure we've noted the complete recursion group of each type as well. - auto recGroup = ht.getRecGroup(); - if (includedGroups.insert(recGroup).second) { - for (auto type : recGroup) { - if (!counts.count(type)) { - newTypes.insert(type); - counts.include(type); + if (!prune) { + auto recGroup = ht.getRecGroup(); + if (includedGroups.insert(recGroup).second) { + for (auto type : recGroup) { + if (!counts.count(type)) { + newTypes.insert(type); + counts.include(type); + } } } } @@ -297,11 +317,11 @@ std::vector<HeapType> getPublicHeapTypes(Module& wasm) { } std::vector<HeapType> getPrivateHeapTypes(Module& wasm) { - auto allTypes = getHeapTypeCounts(wasm); + auto allTypes = getHeapTypeCounts(wasm, true); auto publicTypes = getPublicTypeSet(wasm); std::vector<HeapType> types; types.reserve(allTypes.size() - publicTypes.size()); - for (auto [type, _] : allTypes) { + for (auto& [type, _] : allTypes) { if (!publicTypes.count(type)) { types.push_back(type); } diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt index e97f5e388..f29e7db9b 100644 --- a/src/passes/CMakeLists.txt +++ b/src/passes/CMakeLists.txt @@ -94,6 +94,7 @@ set(passes_SOURCES RemoveUnusedBrs.cpp RemoveUnusedNames.cpp RemoveUnusedModuleElements.cpp + RemoveUnusedTypes.cpp ReorderFunctions.cpp ReorderGlobals.cpp ReorderLocals.cpp diff --git a/src/passes/RemoveUnusedTypes.cpp b/src/passes/RemoveUnusedTypes.cpp new file mode 100644 index 000000000..d346bc585 --- /dev/null +++ b/src/passes/RemoveUnusedTypes.cpp @@ -0,0 +1,48 @@ +/* + * Copyright 2022 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// Remove unused types from private rec groups. This is done implicitly by other +// type optimizations as well, but only if they find anything else they want to +// optimize. +// + +#include "ir/module-utils.h" +#include "ir/type-updating.h" +#include "pass.h" + +namespace wasm { + +namespace { + +struct RemoveUnusedTypes : Pass { + void run(Module* module) override { + if (!module->features.hasGC()) { + // This pass only does anything with GC types. + return; + } + // We're not changing the contents of any of the types, so we just round + // trip them throgh GlobalTypeRewriter, which will put all the private types + // in a single new rec group and leave out all the unused types. + GlobalTypeRewriter(*module).update(); + } +}; + +} // anonymous namespace + +Pass* createRemoveUnusedTypesPass() { return new RemoveUnusedTypes(); } + +} // namespace wasm diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index 21501c62f..732c2e8e2 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -369,6 +369,9 @@ void PassRegistry::registerPasses() { registerPass("remove-unused-names", "removes names from locations that are never branched to", createRemoveUnusedNamesPass); + registerPass("remove-unused-types", + "remove unused private GC types", + createRemoveUnusedTypesPass); registerPass("reorder-functions", "sorts functions by access frequency", createReorderFunctionsPass); @@ -620,6 +623,7 @@ void PassRunner::addDefaultGlobalOptimizationPrePasses() { } addIfNoDWARFIssues("remove-unused-module-elements"); if (options.closedWorld) { + addIfNoDWARFIssues("remove-unused-types"); addIfNoDWARFIssues("cfp"); addIfNoDWARFIssues("gsi"); } diff --git a/src/passes/passes.h b/src/passes/passes.h index 8133c867e..4d6da0ca9 100644 --- a/src/passes/passes.h +++ b/src/passes/passes.h @@ -116,6 +116,7 @@ Pass* createRemoveUnusedBrsPass(); Pass* createRemoveUnusedModuleElementsPass(); Pass* createRemoveUnusedNonFunctionModuleElementsPass(); Pass* createRemoveUnusedNamesPass(); +Pass* createRemoveUnusedTypesPass(); Pass* createReorderFunctionsPass(); Pass* createReorderGlobalsPass(); Pass* createReorderGlobalsAlwaysPass(); |