diff --git a/scripts/test/fuzzing.py b/scripts/test/fuzzing.py index 32b4f44f078..a9f450e5055 100644 --- a/scripts/test/fuzzing.py +++ b/scripts/test/fuzzing.py @@ -103,6 +103,7 @@ 'stack_switching_switch.wast', # TODO: fuzzer support for exact references 'exact-references.wast', + 'optimize-instructions-exact.wast', ] diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index c8c192685a2..0987ed845d6 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -2346,18 +2346,20 @@ struct OptimizeInstructions } [[fallthrough]]; case GCTypeUtils::SuccessOnlyIfNull: { - auto nullType = Type(curr->type.getHeapType().getBottom(), Nullable); // The cast either returns null or traps. In trapsNeverHappen mode // we know the result, since by assumption it will not trap. if (getPassOptions().trapsNeverHappen) { - replaceCurrent(builder.makeBlock( - {builder.makeDrop(curr->ref), builder.makeRefNull(nullType)}, - curr->type)); + replaceCurrent( + builder.makeBlock({builder.makeDrop(curr->ref), + builder.makeRefNull(curr->type.getHeapType())}, + curr->type)); return; } // Otherwise, we should have already refined the cast type to cast - // directly to null. - assert(curr->type == nullType); + // directly to null. We do not further refine the cast type to exact + // null because the extra precision is not useful and doing so would + // increase the size of the instruction encoding. + assert(curr->type.isNull()); break; } case GCTypeUtils::Unreachable: diff --git a/test/lit/passes/optimize-instructions-exact.wast b/test/lit/passes/optimize-instructions-exact.wast new file mode 100644 index 00000000000..ae35380c9a1 --- /dev/null +++ b/test/lit/passes/optimize-instructions-exact.wast @@ -0,0 +1,24 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. + +;; Check that optimizations on casts involving exact reference types work +;; correctly. + +;; RUN: wasm-opt %s -all --optimize-instructions -S -o - | filecheck %s + +(module + ;; CHECK: (func $cast-to-exact-none (type $0) (param $0 anyref) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.cast (exact nullref) + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $cast-to-exact-none (param anyref) + (drop + ;; This will not be changed, but should not trigger an assertion. + (ref.cast (exact nullref) + (local.get 0) + ) + ) + ) +)