diff options
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 15 | ||||
-rw-r--r-- | test/lit/passes/optimize-instructions-gc.wast | 4 |
2 files changed, 17 insertions, 2 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 6b2a5a1cd..c2142fe6c 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1595,6 +1595,21 @@ struct OptimizeInstructions } } + // A nullable cast can be turned into a non-nullable one: + // + // (struct.get ;; or something else that traps on a null ref + // (ref.cast null + // => + // (struct.get + // (ref.cast ;; now non-nullable + // + // Either way we trap here, but refining the type may have benefits later. + if (ref->type.isNullable()) { + if (auto* cast = ref->dynCast<RefCast>()) { + cast->type = Type(cast->type.getHeapType(), NonNullable); + } + } + auto fallthrough = Properties::getFallthrough(ref, getPassOptions(), *getModule()); diff --git a/test/lit/passes/optimize-instructions-gc.wast b/test/lit/passes/optimize-instructions-gc.wast index 592ec80cd..9ca0c81e0 100644 --- a/test/lit/passes/optimize-instructions-gc.wast +++ b/test/lit/passes/optimize-instructions-gc.wast @@ -993,7 +993,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (struct.get_u $struct $i8 - ;; CHECK-NEXT: (ref.cast null $struct + ;; CHECK-NEXT: (ref.cast $struct ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) @@ -1016,7 +1016,7 @@ ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: (drop ;; NOMNL-NEXT: (struct.get_u $struct $i8 - ;; NOMNL-NEXT: (ref.cast null $struct + ;; NOMNL-NEXT: (ref.cast $struct ;; NOMNL-NEXT: (local.get $x) ;; NOMNL-NEXT: ) ;; NOMNL-NEXT: ) |