Skip to content

Commit 2bddedc

Browse files
authored
Update RemoveUnusedBrs for exact references (#7360)
When optimizing branching casts, RemoveUnusedBrs previously assumed that if a source reference type was not a subtype of another target reference type, but the source's heap type was a subtype of the target's heap type, then it could use ref.as_non_null to convert from the source to the target. This is no longer true now that we have exact types because the types may differ in their exactness rather than in their nullness. Update the check guarding the use of ref.as_non_null to specifically check that a non-nullable version of the source type is a subtype of the destination type and add a test.
1 parent 3f59a7d commit 2bddedc

File tree

3 files changed

+43
-2
lines changed

3 files changed

+43
-2
lines changed

scripts/test/fuzzing.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
'local-subtyping-exact.wast',
108108
'remove-unused-types-exact.wast',
109109
'coalesce-locals-exact.wast',
110+
'remove-unused-brs-exact.wast',
110111
]
111112

112113

src/passes/RemoveUnusedBrs.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -859,8 +859,8 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
859859
if (Type::isSubType(expr->type, type)) {
860860
return expr;
861861
}
862-
if (HeapType::isSubType(expr->type.getHeapType(),
863-
type.getHeapType())) {
862+
if (type.isNonNullable() && expr->type.isNullable() &&
863+
Type::isSubType(expr->type.with(NonNullable), type)) {
864864
return builder.makeRefAs(RefAsNonNull, expr);
865865
}
866866
return builder.makeRefCast(expr, type);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
2+
3+
;; RUN: wasm-opt %s -all --remove-unused-brs -S -o - | filecheck %s
4+
5+
;; Check that we optimize the cast correctly when the fallthrough has exact
6+
;; type. In particular, we should not insert a ref.as_non_null, which would
7+
;; trap.
8+
9+
(module
10+
;; CHECK: (func $br_on_cast_fail (type $0) (param $0 (exact nullref))
11+
;; CHECK-NEXT: (local $1 nullref)
12+
;; CHECK-NEXT: (drop
13+
;; CHECK-NEXT: (block $block
14+
;; CHECK-NEXT: (drop
15+
;; CHECK-NEXT: (ref.cast (exact nullref)
16+
;; CHECK-NEXT: (local.tee $1
17+
;; CHECK-NEXT: (local.get $0)
18+
;; CHECK-NEXT: )
19+
;; CHECK-NEXT: )
20+
;; CHECK-NEXT: )
21+
;; CHECK-NEXT: (return)
22+
;; CHECK-NEXT: )
23+
;; CHECK-NEXT: )
24+
;; CHECK-NEXT: )
25+
(func $br_on_cast_fail (param (ref null exact none))
26+
(local $1 nullref)
27+
(drop
28+
(block $block (result (ref none))
29+
(drop
30+
(br_on_cast_fail $block nullref nullref
31+
(local.tee $1
32+
(local.get 0)
33+
)
34+
)
35+
)
36+
(return)
37+
)
38+
)
39+
)
40+
)

0 commit comments

Comments
 (0)