diff options
author | Alon Zakai <azakai@google.com> | 2023-09-18 16:08:23 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-18 16:08:23 -0700 |
commit | 389fa79e63ff20fa1c6c24dfe26a28b2f487cac8 (patch) | |
tree | ae8f9fd92fbc723bff8652edd819d6573571470a /src | |
parent | 6d2364b55e4c81b0b2f7d15778619c40d1ded4d3 (diff) | |
download | binaryen-389fa79e63ff20fa1c6c24dfe26a28b2f487cac8.tar.gz binaryen-389fa79e63ff20fa1c6c24dfe26a28b2f487cac8.tar.bz2 binaryen-389fa79e63ff20fa1c6c24dfe26a28b2f487cac8.zip |
Add passes to finalize or unfinalize types (#5944)
TypeFinalization finalizes all types that we can, that is, all private types that have no
children. TypeUnFinalization unfinalizes (opens) all (private) types.
These could be used by first opening all types, optimizing, and then finalizing, as that
might find more opportunities.
Fixes #5933
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/type-updating.cpp | 3 | ||||
-rw-r--r-- | src/ir/type-updating.h | 8 | ||||
-rw-r--r-- | src/passes/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/passes/TypeFinalizing.cpp | 88 | ||||
-rw-r--r-- | src/passes/pass.cpp | 6 | ||||
-rw-r--r-- | src/passes/passes.h | 2 |
6 files changed, 108 insertions, 0 deletions
diff --git a/src/ir/type-updating.cpp b/src/ir/type-updating.cpp index cca0d2360..59b77cca1 100644 --- a/src/ir/type-updating.cpp +++ b/src/ir/type-updating.cpp @@ -115,6 +115,9 @@ GlobalTypeRewriter::TypeMap GlobalTypeRewriter::rebuildTypes() { typeBuilder[i].subTypeOf(*super); } } + + modifyTypeBuilderEntry(typeBuilder, i, type); + i++; } diff --git a/src/ir/type-updating.h b/src/ir/type-updating.h index 31fd77c69..ddeb74b31 100644 --- a/src/ir/type-updating.h +++ b/src/ir/type-updating.h @@ -373,6 +373,14 @@ public: virtual void modifyArray(HeapType oldType, Array& array) {} virtual void modifySignature(HeapType oldType, Signature& sig) {} + // This additional hook is called after modify* and other operations, and + // allows the caller to do things like typeBuilder[i].setOpen(false); + // + // This is provided the builder, the index we are on, and the old heap type + // for that index. + virtual void + modifyTypeBuilderEntry(TypeBuilder& typeBuilder, Index i, HeapType oldType) {} + // Subclasses can override this method to modify supertypes. The new // supertype, if any, must be a supertype (or the same as) the original // supertype. diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt index a47333cf6..bd29bfa0b 100644 --- a/src/passes/CMakeLists.txt +++ b/src/passes/CMakeLists.txt @@ -114,6 +114,7 @@ set(passes_SOURCES StripEH.cpp SSAify.cpp TupleOptimization.cpp + TypeFinalizing.cpp Untee.cpp Vacuum.cpp ${CMAKE_CURRENT_BINARY_DIR}/WasmIntrinsics.cpp diff --git a/src/passes/TypeFinalizing.cpp b/src/passes/TypeFinalizing.cpp new file mode 100644 index 000000000..ebf04318a --- /dev/null +++ b/src/passes/TypeFinalizing.cpp @@ -0,0 +1,88 @@ +/* + * Copyright 2023 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. + */ + +// +// Make all types final or unfinal (open). A typical workflow might be to un- +// finalize all types, optimize a lot, and then finalize at the end. +// + +#include "ir/module-utils.h" +#include "ir/subtypes.h" +#include "ir/type-updating.h" +#include "pass.h" +#include "wasm-type.h" +#include "wasm.h" + +namespace wasm { + +namespace { + +struct TypeFinalizing : public Pass { + // Whether we should finalize or unfinalize types. + bool finalize; + + // We will only modify types that we are allowed to. + std::unordered_set<HeapType> modifiableTypes; + + TypeFinalizing(bool finalize) : finalize(finalize) {} + + void run(Module* module) override { + if (!module->features.hasGC()) { + return; + } + + // To make a type final, it must have no subtypes. + std::optional<SubTypes> subTypes; + if (finalize) { + subTypes = SubTypes(*module); + } + + auto privateTypes = ModuleUtils::getPrivateHeapTypes(*module); + for (auto type : privateTypes) { + // If we are finalizing types then we can only do that to leaf types. If + // we are unfinalizing, we can do that unconditionally. + if (!finalize || subTypes->getImmediateSubTypes(type).empty()) { + modifiableTypes.insert(type); + } + } + + class TypeRewriter : public GlobalTypeRewriter { + TypeFinalizing& parent; + + public: + TypeRewriter(Module& wasm, TypeFinalizing& parent) + : GlobalTypeRewriter(wasm), parent(parent) {} + + void modifyTypeBuilderEntry(TypeBuilder& typeBuilder, + Index i, + HeapType oldType) override { + if (parent.modifiableTypes.count(oldType)) { + typeBuilder[i].setOpen(!parent.finalize); + } + } + }; + + TypeRewriter(*module, *this).update(); + } +}; + +} // anonymous namespace + +Pass* createTypeFinalizingPass() { return new TypeFinalizing(true); } + +Pass* createTypeUnFinalizingPass() { return new TypeFinalizing(false); } + +} // namespace wasm diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index 15e8c1f26..3880519da 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -483,12 +483,18 @@ void PassRegistry::registerPasses() { registerPass("tuple-optimization", "optimize trivial tuples away", createTupleOptimizationPass); + registerPass("type-finalizing", + "mark all leaf types as final", + createTypeFinalizingPass); registerPass("type-merging", "merge types to their supertypes where possible", createTypeMergingPass); registerPass("type-ssa", "create new nominal types to help other optimizations", createTypeSSAPass); + registerPass("type-unfinalizing", + "mark all types as non-final (open)", + createTypeUnFinalizingPass); registerPass("untee", "removes local.tees, replacing them with sets and gets", createUnteePass); diff --git a/src/passes/passes.h b/src/passes/passes.h index 1cd2a5672..f84cfcaab 100644 --- a/src/passes/passes.h +++ b/src/passes/passes.h @@ -155,8 +155,10 @@ Pass* createTrapModeClamp(); Pass* createTrapModeJS(); Pass* createTupleOptimizationPass(); Pass* createTypeRefiningPass(); +Pass* createTypeFinalizingPass(); Pass* createTypeMergingPass(); Pass* createTypeSSAPass(); +Pass* createTypeUnFinalizingPass(); Pass* createUnteePass(); Pass* createVacuumPass(); |