Skip to content

Commit d758b00

Browse files
authored
Use GLB in PossibleContents::intersect (#7550)
Use the standard utility rather than reimplementing type intersection. The new code is simpler, shorter, and properly supports exactness, avoiding an assertion failure in the added test case. The other functional change is that when one of the intersected heap types is bottom and the type GLB is a non-nullable reference to bottom, the result of the intersection is `None` where it was previously a `Cone`.
1 parent e6d02fa commit d758b00

File tree

3 files changed

+49
-31
lines changed

3 files changed

+49
-31
lines changed

src/ir/possible-contents.cpp

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -182,47 +182,26 @@ void PossibleContents::intersect(const PossibleContents& other) {
182182
auto heapType = type.getHeapType();
183183
auto otherHeapType = otherType.getHeapType();
184184

185-
// If both inputs are nullable then the intersection is nullable as well.
186-
auto nullability =
187-
type.isNullable() && otherType.isNullable() ? Nullable : NonNullable;
185+
// Intersect the types.
186+
auto newType = Type::getGreatestLowerBound(type, otherType);
188187

189188
auto setNoneOrNull = [&]() {
190-
if (nullability == Nullable) {
189+
if (newType.isNullable()) {
191190
value = Literal::makeNull(heapType);
192191
} else {
193192
value = None();
194193
}
195194
};
196195

197-
// If the heap types are not compatible then they are in separate hierarchies
198-
// and there is no intersection, aside from possibly a null of the bottom
199-
// type.
200-
auto isSubType = HeapType::isSubType(heapType, otherHeapType);
201-
auto otherIsSubType = HeapType::isSubType(otherHeapType, heapType);
202-
if (!isSubType && !otherIsSubType) {
203-
if (heapType.getBottom() == otherHeapType.getBottom()) {
204-
setNoneOrNull();
205-
} else {
206-
value = None();
207-
}
196+
if (newType == Type::unreachable || newType.isNull()) {
197+
setNoneOrNull();
208198
return;
209199
}
210200

211201
// The heap types are compatible, so intersect the cones.
212202
auto depthFromRoot = heapType.getDepth();
213203
auto otherDepthFromRoot = otherHeapType.getDepth();
214204

215-
// To compute the new cone, find the new heap type for it, and to compute its
216-
// depth, consider the adjustments to the existing depths that stem from the
217-
// choice of new heap type.
218-
HeapType newHeapType;
219-
220-
if (depthFromRoot < otherDepthFromRoot) {
221-
newHeapType = otherHeapType;
222-
} else {
223-
newHeapType = heapType;
224-
}
225-
226205
// Note the global's information, if we started as a global. In that case, the
227206
// code below will refine our type but we can remain a global, which we will
228207
// accomplish by restoring our global status at the end.
@@ -231,8 +210,6 @@ void PossibleContents::intersect(const PossibleContents& other) {
231210
globalName = getGlobal();
232211
}
233212

234-
auto newType = Type(newHeapType, nullability);
235-
236213
// By assumption |other| has full depth. Consider the other cone in |this|.
237214
if (hasFullCone()) {
238215
// Both are full cones, so the result is as well.
@@ -252,7 +229,7 @@ void PossibleContents::intersect(const PossibleContents& other) {
252229
// E.g. if |this| is a cone of depth 10, and |otherHeapType| is an immediate
253230
// subtype of |this|, then the new cone must be of depth 9.
254231
auto newDepth = getCone().depth;
255-
if (newHeapType == otherHeapType) {
232+
if (newType.getHeapType() == otherHeapType) {
256233
assert(depthFromRoot <= otherDepthFromRoot);
257234
auto reduction = otherDepthFromRoot - depthFromRoot;
258235
if (reduction > newDepth) {

test/lit/passes/gufa-cast-all-exact.wast

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,39 @@
138138
)
139139
)
140140
)
141+
142+
(module
143+
;; CHECK: (type $foo (sub (struct (field i32))))
144+
;; NO_CD: (type $foo (sub (struct (field i32))))
145+
(type $foo (sub (struct (field i32))))
146+
147+
;; CHECK: (import "" "" (global $null-exact (ref null (exact $foo))))
148+
;; NO_CD: (import "" "" (global $null-exact (ref null (exact $foo))))
149+
(import "" "" (global $null-exact (ref null (exact $foo))))
150+
151+
;; CHECK: (func $as-non-null (type $1) (result i32)
152+
;; CHECK-NEXT: (drop
153+
;; CHECK-NEXT: (ref.as_non_null
154+
;; CHECK-NEXT: (global.get $null-exact)
155+
;; CHECK-NEXT: )
156+
;; CHECK-NEXT: )
157+
;; CHECK-NEXT: (unreachable)
158+
;; CHECK-NEXT: )
159+
;; NO_CD: (func $as-non-null (type $1) (result i32)
160+
;; NO_CD-NEXT: (drop
161+
;; NO_CD-NEXT: (ref.as_non_null
162+
;; NO_CD-NEXT: (global.get $null-exact)
163+
;; NO_CD-NEXT: )
164+
;; NO_CD-NEXT: )
165+
;; NO_CD-NEXT: (unreachable)
166+
;; NO_CD-NEXT: )
167+
(func $as-non-null (result i32)
168+
(struct.get $foo 0
169+
;; Regression test for an assertion failure when the intersection here
170+
;; dropped exactness as well as nullness.
171+
(ref.as_non_null
172+
(global.get $null-exact)
173+
)
174+
)
175+
)
176+
)

test/lit/passes/gufa-refs.wast

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6069,8 +6069,13 @@
60696069
;; CHECK: (func $test-set-bottom (type $2)
60706070
;; CHECK-NEXT: (block ;; (replaces unreachable ArraySet we can't emit)
60716071
;; CHECK-NEXT: (drop
6072-
;; CHECK-NEXT: (ref.cast nullref
6073-
;; CHECK-NEXT: (global.get $global)
6072+
;; CHECK-NEXT: (block (result nullref)
6073+
;; CHECK-NEXT: (drop
6074+
;; CHECK-NEXT: (ref.cast nullref
6075+
;; CHECK-NEXT: (global.get $global)
6076+
;; CHECK-NEXT: )
6077+
;; CHECK-NEXT: )
6078+
;; CHECK-NEXT: (ref.null none)
60746079
;; CHECK-NEXT: )
60756080
;; CHECK-NEXT: )
60766081
;; CHECK-NEXT: (drop

0 commit comments

Comments
 (0)