Skip to content

Commit cdcf62b

Browse files
authored
Fix missing Exact type ReFinalization in TypeMerging (#7619)
If we merge siblings to their parent, they may end up equal: (select (result A)) (B1) (B2) ) => (select (result (exact A))) ;; result is now exact (A) ;; both are (A) ;; now A ) In such cases we must refinalize, as the LUB is now exact.
1 parent 7607db6 commit cdcf62b

File tree

3 files changed

+58
-4
lines changed

3 files changed

+58
-4
lines changed

src/passes/TypeMerging.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,22 @@ void TypeMerging::run(Module* module_) {
245245
//
246246
// If we merge siblings, we also need to refinalize because the LUB of merged
247247
// siblings is the merged type rather than their common supertype after the
248-
// merge.
249-
bool refinalize = false;
250-
merge(Supertypes);
248+
// merge. This can happen in merge(Siblings), but also in merge(Supertypes),
249+
// since we may end up merging B1 to its super A, and also B2 to the same
250+
// super A, ending up with B1 and B2 now equal - in that case the siblings are
251+
// now both equal (to the parent), allowing an exact LUB:
252+
//
253+
// (select (result A))
254+
// (B1)
255+
// (B2)
256+
// )
257+
// =>
258+
// (select (result (exact A))) ;; result is now exact
259+
// (A) ;; both are
260+
// (A) ;; now A
261+
// )
262+
//
263+
bool refinalize = merge(Supertypes);
251264
for (int i = 0; i < MAX_ITERATIONS; ++i) {
252265
if (!merge(Siblings)) {
253266
break;

test/lit/passes/type-merging-exact.wast

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,44 @@
131131
)
132132
)
133133
)
134+
135+
;; Merge two siblings to their parent. We must refinalize here.
136+
(module
137+
(rec
138+
;; CHECK: (rec
139+
;; CHECK-NEXT: (type $A (sub (array i8)))
140+
(type $A (sub (array i8)))
141+
(type $B1 (sub $A (array i8)))
142+
(type $B2 (sub $A (array i8)))
143+
)
144+
145+
;; CHECK: (func $test (type $1)
146+
;; CHECK-NEXT: (drop
147+
;; CHECK-NEXT: (select (result (ref (exact $A)))
148+
;; CHECK-NEXT: (array.new_default $A
149+
;; CHECK-NEXT: (i32.const 0)
150+
;; CHECK-NEXT: )
151+
;; CHECK-NEXT: (array.new_default $A
152+
;; CHECK-NEXT: (i32.const 1)
153+
;; CHECK-NEXT: )
154+
;; CHECK-NEXT: (i32.const 2)
155+
;; CHECK-NEXT: )
156+
;; CHECK-NEXT: )
157+
;; CHECK-NEXT: )
158+
(func $test
159+
;; B1 and B2 will turn into A, after which the select can be refined to an
160+
;; exact type.
161+
(drop
162+
(select (result (ref $A))
163+
(array.new_default $B1
164+
(i32.const 0)
165+
)
166+
(array.new_default $B2
167+
(i32.const 1)
168+
)
169+
(i32.const 2)
170+
)
171+
)
172+
)
173+
)
174+

test/lit/passes/type-merging.wast

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,7 @@
890890
)
891891

892892
;; CHECK: (func $test (type $D) (result (ref any) (ref $B))
893-
;; CHECK-NEXT: (block $l (type $A) (result (ref any) (ref $B))
893+
;; CHECK-NEXT: (block $l
894894
;; CHECK-NEXT: (unreachable)
895895
;; CHECK-NEXT: )
896896
;; CHECK-NEXT: )

0 commit comments

Comments
 (0)