diff options
31 files changed, 101 insertions, 252 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 62a7af564..50072ebb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ Current Trunk - C API: Add BinaryenAddFunctionWithHeapType() which is like BinaryenAddFunction but takes a heap type. The old function is kept for backwards compatibility and as a convenience. +- The nonstandard, experimental gc-nn-locals feature has been removed now that + standard non-nullable locals are supported. v114 ---- diff --git a/src/ir/type-updating.cpp b/src/ir/type-updating.cpp index ac1f4b3af..0bc14763b 100644 --- a/src/ir/type-updating.cpp +++ b/src/ir/type-updating.cpp @@ -307,10 +307,6 @@ bool canHandleAsLocal(Type type) { } void handleNonDefaultableLocals(Function* func, Module& wasm) { - if (wasm.features.hasGCNNLocals()) { - // We have nothing to fix up: all locals are allowed. - return; - } if (!wasm.features.hasReferenceTypes()) { // No references, so no non-nullable ones at all. return; @@ -404,9 +400,6 @@ void handleNonDefaultableLocals(Function* func, Module& wasm) { Type getValidLocalType(Type type, FeatureSet features) { assert(type.isConcrete()); - if (features.hasGCNNLocals()) { - return type; - } if (type.isNonNullable()) { return Type(type.getHeapType(), Nullable); } @@ -421,9 +414,6 @@ Type getValidLocalType(Type type, FeatureSet features) { } Expression* fixLocalGet(LocalGet* get, Module& wasm) { - if (wasm.features.hasGCNNLocals()) { - return get; - } if (get->type.isNonNullable()) { // The get should now return a nullable value, and a ref.as_non_null // fixes that up. diff --git a/src/passes/Flatten.cpp b/src/passes/Flatten.cpp index e8dec3010..3c0aa78a0 100644 --- a/src/passes/Flatten.cpp +++ b/src/passes/Flatten.cpp @@ -33,11 +33,9 @@ // ) // ) // -// The tuple has a non-nullable type, and so it cannot be set to a local. We -// would need to split up the tuple and reconstruct it later, but that would -// require allowing tuple operations in more nested places than Flat IR allows -// today. For now, error on this; eventually changes in the spec regarding -// null-nullability may make this easier. +// The tuple has a non-nullable type, and so it cannot currently be set to a +// local, but in principle there's no reason it couldn't be. For now, error on +// this. #include <ir/branch-utils.h> #include <ir/effects.h> diff --git a/src/passes/LocalSubtyping.cpp b/src/passes/LocalSubtyping.cpp index eeaaaaefa..ad0cfa7d2 100644 --- a/src/passes/LocalSubtyping.cpp +++ b/src/passes/LocalSubtyping.cpp @@ -78,27 +78,11 @@ struct LocalSubtyping : public WalkerPass<PostWalker<LocalSubtyping>> { // Find which vars can be non-nullable. std::unordered_set<Index> cannotBeNonNullable; - if (getModule()->features.hasGCNNLocals()) { - // If the feature is enabled then the only constraint is being able to - // read the default value - if it is readable, the local cannot become - // non-nullable. - for (auto& [get, sets] : localGraph.getSetses) { - auto index = get->index; - if (func->isVar(index) && - std::any_of(sets.begin(), sets.end(), [&](LocalSet* set) { - return set == nullptr; - })) { - cannotBeNonNullable.insert(index); - } - } - } else { - // Without GCNNLocals, validation rules follow the spec rules: all gets - // must be dominated structurally by sets, for the local to be non- - // nullable. - LocalStructuralDominance info(func, *getModule()); - for (auto index : info.nonDominatingIndices) { - cannotBeNonNullable.insert(index); - } + // All gets must be dominated structurally by sets for the local to be non- + // nullable. + LocalStructuralDominance info(func, *getModule()); + for (auto index : info.nonDominatingIndices) { + cannotBeNonNullable.insert(index); } auto varBase = func->getVarIndexBase(); diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index f15bac23d..0b787105e 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1155,17 +1155,9 @@ struct OptimizeInstructions void visitLocalSet(LocalSet* curr) { // Interactions between local.set/tee and ref.as_non_null can be optimized - // in some cases, by removing or moving the ref.as_non_null operation. In - // all cases, we only do this when we do *not* allow non-nullable locals. If - // we do allow such locals, then (1) this local might be non-nullable, so we - // can't remove or move a ref.as_non_null flowing into a local.set/tee, and - // (2) even if the local were nullable, if we change things we might prevent - // the LocalSubtyping pass from turning it into a non-nullable local later. - // Note that we must also check if this local is nullable regardless, as a - // parameter might be non-nullable even if nullable locals are disallowed - // (as that just affects vars, and not params). + // in some cases, by removing or moving the ref.as_non_null operation. if (auto* as = curr->value->dynCast<RefAs>()) { - if (as->op == RefAsNonNull && !getModule()->features.hasGCNNLocals() && + if (as->op == RefAsNonNull && getFunction()->getLocalType(curr->index).isNullable()) { // (local.tee (ref.as_non_null ..)) // => diff --git a/src/tools/tool-options.h b/src/tools/tool-options.h index 6f3b4968c..f7dd791b4 100644 --- a/src/tools/tool-options.h +++ b/src/tools/tool-options.h @@ -89,7 +89,6 @@ struct ToolOptions : public Options { .addFeature(FeatureSet::Multivalue, "multivalue functions") .addFeature(FeatureSet::GC, "garbage collection") .addFeature(FeatureSet::Memory64, "memory64") - .addFeature(FeatureSet::GCNNLocals, "GC non-null locals") .addFeature(FeatureSet::RelaxedSIMD, "relaxed SIMD") .addFeature(FeatureSet::ExtendedConst, "extended const expressions") .addFeature(FeatureSet::Strings, "strings") diff --git a/src/wasm-features.h b/src/wasm-features.h index 197b6eb36..f8d006e78 100644 --- a/src/wasm-features.h +++ b/src/wasm-features.h @@ -40,21 +40,15 @@ struct FeatureSet { Multivalue = 1 << 9, GC = 1 << 10, Memory64 = 1 << 11, - // TODO: Remove this feature when the wasm spec stabilizes. - GCNNLocals = 1 << 12, - RelaxedSIMD = 1 << 13, - ExtendedConst = 1 << 14, - Strings = 1 << 15, - MultiMemory = 1 << 16, + RelaxedSIMD = 1 << 12, + ExtendedConst = 1 << 13, + Strings = 1 << 14, + MultiMemory = 1 << 15, MVP = None, // Keep in sync with llvm default features: // https://github.com/llvm/llvm-project/blob/c7576cb89d6c95f03968076e902d3adfd1996577/clang/lib/Basic/Targets/WebAssembly.cpp#L150-L153 Default = SignExt | MutableGlobals, - // GCNNLocals are opt-in: merely asking for "All" does not apply them. To - // get all possible values use AllPossible. See setAll() below for more - // details. - All = ((1 << 17) - 1) & ~GCNNLocals, - AllPossible = (1 << 17) - 1, + All = (1 << 16) - 1, }; static std::string toString(Feature f) { @@ -83,8 +77,6 @@ struct FeatureSet { return "gc"; case Memory64: return "memory64"; - case GCNNLocals: - return "gc-nn-locals"; case RelaxedSIMD: return "relaxed-simd"; case ExtendedConst: @@ -101,7 +93,7 @@ struct FeatureSet { std::string toString() const { std::string ret; uint32_t x = 1; - while (x & Feature::AllPossible) { + while (x & Feature::All) { if (features & x) { if (!ret.empty()) { ret += ", "; @@ -133,12 +125,11 @@ struct FeatureSet { bool hasMultivalue() const { return (features & Multivalue) != 0; } bool hasGC() const { return (features & GC) != 0; } bool hasMemory64() const { return (features & Memory64) != 0; } - bool hasGCNNLocals() const { return (features & GCNNLocals) != 0; } bool hasRelaxedSIMD() const { return (features & RelaxedSIMD) != 0; } bool hasExtendedConst() const { return (features & ExtendedConst) != 0; } bool hasStrings() const { return (features & Strings) != 0; } bool hasMultiMemory() const { return (features & MultiMemory) != 0; } - bool hasAll() const { return (features & AllPossible) != 0; } + bool hasAll() const { return (features & All) != 0; } void set(FeatureSet f, bool v = true) { features = v ? (features | f) : (features & ~f); @@ -155,34 +146,18 @@ struct FeatureSet { void setMultivalue(bool v = true) { set(Multivalue, v); } void setGC(bool v = true) { set(GC, v); } void setMemory64(bool v = true) { set(Memory64, v); } - void setGCNNLocals(bool v = true) { set(GCNNLocals, v); } void setRelaxedSIMD(bool v = true) { set(RelaxedSIMD, v); } void setExtendedConst(bool v = true) { set(ExtendedConst, v); } void setStrings(bool v = true) { set(Strings, v); } void setMultiMemory(bool v = true) { set(MultiMemory, v); } void setMVP() { features = MVP; } - void setAll() { - // Do not set GCNNLocals, which forces the user to opt in to that feature - // explicitly. That is, wasm-opt -all will enable GC but *not* enable - // non-nullable locals. To get them, do wasm-opt -all --enable-gc-nn-locals - // FIXME: When the wasm spec stabilizes, this feature will go away, as the - // non-nullable locals experiment will either become the standard, - // or it will go away. - // Leave the old GCNNLocals value unmodified. This makes things like - // --enable-gc-nn-locals -all work (that is, if we enable the feature, - // then -all does not disable it; it simply does not enable it by itself). - auto oldGCNNLocals = hasGCNNLocals(); - features = AllPossible; - setGCNNLocals(oldGCNNLocals); - } + void setAll() { features = All; } void enable(const FeatureSet& other) { features |= other.features; } - void disable(const FeatureSet& other) { - features = features & ~other.features & AllPossible; - } + void disable(const FeatureSet& other) { features &= ~other.features; } template<typename F> void iterFeatures(F f) const { - for (uint32_t feature = MVP + 1; feature < AllPossible; feature <<= 1) { + for (uint32_t feature = MVP + 1; feature < All; feature <<= 1) { if (has(feature)) { f(static_cast<Feature>(feature)); } diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 011957cd3..7a0a08885 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -2627,9 +2627,7 @@ void WasmBinaryReader::readFunctions() { } } - if (!wasm.features.hasGCNNLocals()) { - TypeUpdating::handleNonDefaultableLocals(func, wasm); - } + TypeUpdating::handleNonDefaultableLocals(func, wasm); std::swap(func->epilogLocation, debugLocation); currFunction = nullptr; diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 289d10b96..d6575f7d4 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -3195,45 +3195,13 @@ void FunctionValidator::visitFunction(Function* curr) { if (getModule()->features.hasGC()) { // If we have non-nullable locals, verify that local.get are valid. - if (!getModule()->features.hasGCNNLocals()) { - // Without the special GCNNLocals feature, we implement the spec rules, - // that is, a set allows gets until the end of the block. - LocalStructuralDominance info(curr, *getModule()); - for (auto index : info.nonDominatingIndices) { - auto localType = curr->getLocalType(index); - for (auto type : localType) { - shouldBeTrue(!type.isNonNullable(), - index, - "non-nullable local's sets must dominate gets"); - } - } - } else { - // With the special GCNNLocals feature, we allow gets anywhere, so long as - // we can prove they cannot read the null value. (TODO: remove this once - // the spec is stable). - // - // This is slow, so only do it if we find such locals exist at all. - bool hasNNLocals = false; - for (const auto& var : curr->vars) { - if (!var.isDefaultable()) { - hasNNLocals = true; - break; - } - } - if (hasNNLocals) { - LocalGraph graph(curr); - for (auto& [get, sets] : graph.getSetses) { - auto index = get->index; - // It is always ok to read nullable locals, and it is always ok to - // read params even if they are non-nullable. - if (curr->getLocalType(index).isDefaultable() || - curr->isParam(index)) { - continue; - } - for (auto* set : sets) { - shouldBeTrue(!!set, index, "non-nullable local must not read null"); - } - } + LocalStructuralDominance info(curr, *getModule()); + for (auto index : info.nonDominatingIndices) { + auto localType = curr->getLocalType(index); + for (auto type : localType) { + shouldBeTrue(!type.isNonNullable(), + index, + "non-nullable local's sets must dominate gets"); } } } diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index 0f67e903b..d8bb8d4ed 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -29,11 +29,11 @@ Features.ReferenceTypes: 256 Features.Multivalue: 512 Features.GC: 1024 Features.Memory64: 2048 -Features.RelaxedSIMD: 8192 -Features.ExtendedConst: 16384 -Features.Strings: 32768 -Features.MultiMemory: 65536 -Features.All: 126975 +Features.RelaxedSIMD: 4096 +Features.ExtendedConst: 8192 +Features.Strings: 16384 +Features.MultiMemory: 32768 +Features.All: 65535 InvalidId: 0 BlockId: 1 IfId: 2 diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index eef40f8cc..cde0e0279 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -50,10 +50,10 @@ BinaryenFeatureReferenceTypes: 256 BinaryenFeatureMultivalue: 512 BinaryenFeatureGC: 1024 BinaryenFeatureMemory64: 2048 -BinaryenFeatureRelaxedSIMD: 8192 -BinaryenFeatureExtendedConst: 16384 -BinaryenFeatureStrings: 32768 -BinaryenFeatureAll: 126975 +BinaryenFeatureRelaxedSIMD: 4096 +BinaryenFeatureExtendedConst: 8192 +BinaryenFeatureStrings: 16384 +BinaryenFeatureAll: 65535 (f32.neg (f32.const -33.61199951171875) ) diff --git a/test/lit/binary/stacky-nn-tuple.test b/test/lit/binary/stacky-nn-tuple.test index 41abc1d7d..e8a0475b5 100644 --- a/test/lit/binary/stacky-nn-tuple.test +++ b/test/lit/binary/stacky-nn-tuple.test @@ -36,7 +36,7 @@ # ) # ) -RUN: wasm-opt -all --enable-gc-nn-locals %s.wasm -all --print +RUN: wasm-opt -all %s.wasm -all --print # CHECK: (module # CHECK-NEXT: (type ${mut:i32} (struct (field (mut i32)))) @@ -109,4 +109,4 @@ RUN: wasm-opt -all --enable-gc-nn-locals %s.wasm -all --print # CHECK-NEXT: ) # CHECK-NEXT: ) # CHECK-NEXT: ) -# CHECK-NEXT: +# CHECK-NEXT: diff --git a/test/lit/help/wasm-as.test b/test/lit/help/wasm-as.test index 0fbbe77be..8cad64a3b 100644 --- a/test/lit/help/wasm-as.test +++ b/test/lit/help/wasm-as.test @@ -88,10 +88,6 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-memory64 Disable memory64 ;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: ;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD diff --git a/test/lit/help/wasm-ctor-eval.test b/test/lit/help/wasm-ctor-eval.test index 7d3b3082a..b93f90b37 100644 --- a/test/lit/help/wasm-ctor-eval.test +++ b/test/lit/help/wasm-ctor-eval.test @@ -95,10 +95,6 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-memory64 Disable memory64 ;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: ;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD diff --git a/test/lit/help/wasm-dis.test b/test/lit/help/wasm-dis.test index 82e8ec829..010a430e8 100644 --- a/test/lit/help/wasm-dis.test +++ b/test/lit/help/wasm-dis.test @@ -81,10 +81,6 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-memory64 Disable memory64 ;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: ;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD diff --git a/test/lit/help/wasm-emscripten-finalize.test b/test/lit/help/wasm-emscripten-finalize.test index 641323c74..4005dd911 100644 --- a/test/lit/help/wasm-emscripten-finalize.test +++ b/test/lit/help/wasm-emscripten-finalize.test @@ -128,10 +128,6 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-memory64 Disable memory64 ;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: ;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD diff --git a/test/lit/help/wasm-merge.test b/test/lit/help/wasm-merge.test index 867275a3c..65acdff40 100644 --- a/test/lit/help/wasm-merge.test +++ b/test/lit/help/wasm-merge.test @@ -99,10 +99,6 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-memory64 Disable memory64 ;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: ;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD diff --git a/test/lit/help/wasm-metadce.test b/test/lit/help/wasm-metadce.test index 655a791a9..2fa50775e 100644 --- a/test/lit/help/wasm-metadce.test +++ b/test/lit/help/wasm-metadce.test @@ -129,10 +129,6 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-memory64 Disable memory64 ;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: ;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD diff --git a/test/lit/help/wasm-opt.test b/test/lit/help/wasm-opt.test index 7c56aa1ab..681128b03 100644 --- a/test/lit/help/wasm-opt.test +++ b/test/lit/help/wasm-opt.test @@ -652,10 +652,6 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-memory64 Disable memory64 ;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: ;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD diff --git a/test/lit/help/wasm-reduce.test b/test/lit/help/wasm-reduce.test index 53405fb4b..693116c09 100644 --- a/test/lit/help/wasm-reduce.test +++ b/test/lit/help/wasm-reduce.test @@ -117,10 +117,6 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-memory64 Disable memory64 ;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: ;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD diff --git a/test/lit/help/wasm-split.test b/test/lit/help/wasm-split.test index 2ca4c2ad0..eac557a9e 100644 --- a/test/lit/help/wasm-split.test +++ b/test/lit/help/wasm-split.test @@ -197,10 +197,6 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-memory64 Disable memory64 ;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: ;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD diff --git a/test/lit/help/wasm2js.test b/test/lit/help/wasm2js.test index 2e52d6ce5..1e34b3617 100644 --- a/test/lit/help/wasm2js.test +++ b/test/lit/help/wasm2js.test @@ -611,10 +611,6 @@ ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-memory64 Disable memory64 ;; CHECK-NEXT: -;; CHECK-NEXT: --enable-gc-nn-locals Enable GC non-null locals -;; CHECK-NEXT: -;; CHECK-NEXT: --disable-gc-nn-locals Disable GC non-null locals -;; CHECK-NEXT: ;; CHECK-NEXT: --enable-relaxed-simd Enable relaxed SIMD ;; CHECK-NEXT: ;; CHECK-NEXT: --disable-relaxed-simd Disable relaxed SIMD diff --git a/test/lit/passes/coalesce-locals-gc-nn.wast b/test/lit/passes/coalesce-locals-gc-nn.wast index 32a34e016..4dfce0242 100644 --- a/test/lit/passes/coalesce-locals-gc-nn.wast +++ b/test/lit/passes/coalesce-locals-gc-nn.wast @@ -1,6 +1,5 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --coalesce-locals -all --enable-gc-nn-locals -S -o - \ -;; RUN: | filecheck %s +;; RUN: wasm-opt %s --coalesce-locals -all -S -o - | filecheck %s (module ;; CHECK: (func $nn-locals (type $0) (param $0 (ref any)) @@ -81,27 +80,4 @@ ) ) ) - - ;; CHECK: (func $unreachable-get-of-non-nullable (type $1) - ;; CHECK-NEXT: (local $0 (ref any)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (block (result (ref any)) - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $unreachable-get-of-non-nullable - ;; One local is unused entirely, the other is used but only in unreachable - ;; code. It does not really matter what we do here (coalesce, or not), but we - ;; should emit valid IR. Normally we would apply a constant to replace the - ;; local.get, however, the types here are non-nullable, so we must do - ;; something else. - (local $unused (ref any)) - (local $used-in-unreachable (ref any)) - (unreachable) - (drop - (local.get $used-in-unreachable) - ) - ) ) diff --git a/test/lit/passes/inlining-gc.wast b/test/lit/passes/inlining-gc.wast index 92267519a..8da522e1d 100644 --- a/test/lit/passes/inlining-gc.wast +++ b/test/lit/passes/inlining-gc.wast @@ -1,5 +1,5 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --inlining --enable-gc-nn-locals -all -S -o - | filecheck %s +;; RUN: wasm-opt %s --inlining -all -S -o - | filecheck %s (module ;; CHECK: (func $caller-nullable (type $0) diff --git a/test/lit/passes/local-subtyping-nn.wast b/test/lit/passes/local-subtyping-nn.wast index c017fb35b..04cade7e0 100644 --- a/test/lit/passes/local-subtyping-nn.wast +++ b/test/lit/passes/local-subtyping-nn.wast @@ -1,6 +1,5 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --local-subtyping -all --enable-gc-nn-locals -S -o - \ -;; RUN: | filecheck %s +;; RUN: wasm-opt %s --local-subtyping -all -S -o - | filecheck %s (module (type $struct (struct)) diff --git a/test/lit/passes/optimize-instructions-gc-tnh-nn.wast b/test/lit/passes/optimize-instructions-gc-tnh-nn.wast deleted file mode 100644 index c5692a692..000000000 --- a/test/lit/passes/optimize-instructions-gc-tnh-nn.wast +++ /dev/null @@ -1,40 +0,0 @@ -;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. -;; RUN: wasm-opt %s --optimize-instructions --traps-never-happen --enable-gc-nn-locals -all -S -o - \ -;; RUN: | filecheck %s - -(module - ;; CHECK: (func $set-of-as-non-null (type $0) - ;; CHECK-NEXT: (local $x anyref) - ;; CHECK-NEXT: (local.set $x - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.tee $x - ;; CHECK-NEXT: (ref.as_non_null - ;; CHECK-NEXT: (local.get $x) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - ;; CHECK-NEXT: ) - (func $set-of-as-non-null - (local $x anyref) - ;; As we ignore such traps, we can in principle remove the ref.as here. - ;; However, as we allow non-nullable locals, we should not do that - if we - ;; did it it might prevent specializing the local type later. - (local.set $x - (ref.as_non_null - (local.get $x) - ) - ) - ;; The same for a tee. - (drop - (local.tee $x - (ref.as_non_null - (local.get $x) - ) - ) - ) - ) -) diff --git a/test/lit/passes/optimize-instructions-gc-tnh.wast b/test/lit/passes/optimize-instructions-gc-tnh.wast index d56b296da..28177f306 100644 --- a/test/lit/passes/optimize-instructions-gc-tnh.wast +++ b/test/lit/passes/optimize-instructions-gc-tnh.wast @@ -977,6 +977,55 @@ ) ) + ;; TNH: (func $set-of-as-non-null (type $void) + ;; TNH-NEXT: (local $x anyref) + ;; TNH-NEXT: (local.set $x + ;; TNH-NEXT: (local.get $x) + ;; TNH-NEXT: ) + ;; TNH-NEXT: (drop + ;; TNH-NEXT: (ref.as_non_null + ;; TNH-NEXT: (local.tee $x + ;; TNH-NEXT: (local.get $x) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; TNH-NEXT: ) + ;; NO_TNH: (func $set-of-as-non-null (type $void) + ;; NO_TNH-NEXT: (local $x anyref) + ;; NO_TNH-NEXT: (local.set $x + ;; NO_TNH-NEXT: (ref.as_non_null + ;; NO_TNH-NEXT: (local.get $x) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: (drop + ;; NO_TNH-NEXT: (ref.as_non_null + ;; NO_TNH-NEXT: (local.tee $x + ;; NO_TNH-NEXT: (local.get $x) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: ) + ;; NO_TNH-NEXT: ) + (func $set-of-as-non-null + (local $x anyref) + ;; We can remove the ref.as_non_null here because the local is nullable and + ;; we are ignoring traps. + ;; TODO: Should we keep the cast to let us refine the local later? + (local.set $x + (ref.as_non_null + (local.get $x) + ) + ) + ;; The same for a tee. + (drop + (local.tee $x + (ref.as_non_null + (local.get $x) + ) + ) + ) + ) + + ;; Helper functions. ;; TNH: (func $get-i32 (type $2) (result i32) diff --git a/test/lit/passes/ssa-gc-nn-locals.wast b/test/lit/passes/ssa-gc-nn-locals.wast index be4a5aee9..2ed36340e 100644 --- a/test/lit/passes/ssa-gc-nn-locals.wast +++ b/test/lit/passes/ssa-gc-nn-locals.wast @@ -1,7 +1,7 @@ ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. ;; -g --roundtrip are added to show that we properly handle non-nullable locals ;; through the binary format as well (-g is for the function names). -;; RUN: wasm-opt %s -all --ssa --enable-gc-nn-locals -g --roundtrip -S -o - | filecheck %s +;; RUN: wasm-opt %s -all --ssa -g --roundtrip -S -o - | filecheck %s (module ;; CHECK: (func $nn-locals (type $0) @@ -19,9 +19,8 @@ (func $nn-locals ;; A non-nullable local (local $x (ref func)) - ;; Set the local, and get it later. The SSA pass will normally handle non- - ;; nullability using ref.as_non_null, but with --gc-nn-locals nothing should - ;; be done. + ;; Set the local, and get it later. The SSA pass handles non- nullability + ;; using ref.as_non_null. (local.set $x (ref.func $nn-locals)) (drop (local.get $x)) (drop (local.get $x)) diff --git a/test/lit/validation/nn-locals-bad-call_ref.wast b/test/lit/validation/nn-locals-bad-call_ref.wast index 9a96ed4bc..cd6aaa378 100644 --- a/test/lit/validation/nn-locals-bad-call_ref.wast +++ b/test/lit/validation/nn-locals-bad-call_ref.wast @@ -1,8 +1,8 @@ ;; Test for validation of non-nullable locals -;; RUN: not wasm-opt -all --enable-gc-nn-locals %s 2>&1 | filecheck %s +;; RUN: not wasm-opt -all %s 2>&1 | filecheck %s -;; CHECK: non-nullable local must not read null +;; CHECK: non-nullable local's sets must dominate gets (module (tag $tag (param i32)) diff --git a/test/lit/validation/nn-locals-bad.wast b/test/lit/validation/nn-locals-bad.wast index 17a5c1404..867db2f47 100644 --- a/test/lit/validation/nn-locals-bad.wast +++ b/test/lit/validation/nn-locals-bad.wast @@ -1,8 +1,8 @@ ;; Test for validation of non-nullable locals -;; RUN: not wasm-opt -all --enable-gc-nn-locals %s 2>&1 | filecheck %s +;; RUN: not wasm-opt -all %s 2>&1 | filecheck %s -;; CHECK: non-nullable local must not read null +;; CHECK: non-nullable local's sets must dominate gets (module (func $foo diff --git a/test/lit/validation/nn-locals-ok.wast b/test/lit/validation/nn-locals-ok.wast index 1dfd20962..18696b5cf 100644 --- a/test/lit/validation/nn-locals-ok.wast +++ b/test/lit/validation/nn-locals-ok.wast @@ -1,6 +1,6 @@ ;; Test for validation of non-nullable locals -;; RUN: wasm-opt -all --enable-gc-nn-locals %s --print | filecheck %s +;; RUN: wasm-opt -all %s --print | filecheck %s ;; CHECK: (module |