Skip to content

Commit 0472ba2

Browse files
authored
Handle exact references when fixing non-defaultable locals (#7357)
Some passes leave non-defaultable locals in an invalid state where not all the gets of the local are structurally dominated by sets. To fix this, the pass runner automatically calls `TypeUpdating::handleNonDefaultableLocals` to find the problematic locals and make them nullable. This function did not previously preserve exactness in the updated local types. Fix it and add a test.
1 parent f0a8b6f commit 0472ba2

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

scripts/test/fuzzing.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
'optimize-instructions-exact.wast',
107107
'local-subtyping-exact.wast',
108108
'remove-unused-types-exact.wast',
109+
'coalesce-locals-exact.wast',
109110
]
110111

111112

src/ir/type-updating.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ void handleNonDefaultableLocals(Function* func, Module& wasm) {
467467
Type getValidLocalType(Type type, FeatureSet features) {
468468
assert(type.isConcrete());
469469
if (type.isNonNullable()) {
470-
return Type(type.getHeapType(), Nullable);
470+
return Type(type.getHeapType(), Nullable, type.getExactness());
471471
}
472472
if (type.isTuple()) {
473473
std::vector<Type> elems(type.size());
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
2+
3+
;; Check that TypeUpdating::handleNonDefaultableLocals handles locals with exact
4+
;; reference types correctly, and in particular that it preserves the exactness
5+
;; of the types.
6+
7+
;; RUN: wasm-opt %s -all --coalesce-locals -S -o - | filecheck %s
8+
9+
(module
10+
;; CHECK: (func $test (type $0) (param $0 (exact i31ref)) (result (ref exact i31))
11+
;; CHECK-NEXT: (local $1 (exact i31ref))
12+
;; CHECK-NEXT: (drop
13+
;; CHECK-NEXT: (ref.as_non_null
14+
;; CHECK-NEXT: (local.get $0)
15+
;; CHECK-NEXT: )
16+
;; CHECK-NEXT: )
17+
;; CHECK-NEXT: (block $l
18+
;; CHECK-NEXT: (local.set $1
19+
;; CHECK-NEXT: (ref.as_non_null
20+
;; CHECK-NEXT: (local.get $0)
21+
;; CHECK-NEXT: )
22+
;; CHECK-NEXT: )
23+
;; CHECK-NEXT: )
24+
;; CHECK-NEXT: (ref.as_non_null
25+
;; CHECK-NEXT: (local.get $1)
26+
;; CHECK-NEXT: )
27+
;; CHECK-NEXT: )
28+
(func $test (param (exact i31ref)) (result (ref exact i31))
29+
(local $l (ref exact i31))
30+
;; This dead set will be optimized out.
31+
(local.set $l
32+
(ref.as_non_null
33+
(local.get 0)
34+
)
35+
)
36+
(block $l
37+
;; This remaining set does not structurally dominate the get.
38+
(local.set $l
39+
(ref.as_non_null
40+
(local.get 0)
41+
)
42+
)
43+
)
44+
;; This will have to be fixed up and the local made nullable.
45+
(local.get $l)
46+
)
47+
)

0 commit comments

Comments
 (0)