@@ -144,7 +144,9 @@ PossibleContents PossibleContents::combine(const PossibleContents& a,
144
144
145
145
void PossibleContents::intersect (const PossibleContents& other) {
146
146
// This does not yet handle all possible content.
147
- assert (other.isFullConeType () || other.isLiteral () || other.isNone ());
147
+ assert ((other.isConeType () &&
148
+ (other.getType ().isExact () || other.hasFullCone ())) ||
149
+ other.isLiteral () || other.isNone ());
148
150
149
151
if (*this == other) {
150
152
// Nothing changes.
@@ -201,6 +203,7 @@ void PossibleContents::intersect(const PossibleContents& other) {
201
203
// The heap types are compatible, so intersect the cones.
202
204
auto depthFromRoot = heapType.getDepth ();
203
205
auto otherDepthFromRoot = otherHeapType.getDepth ();
206
+ auto newDepthFromRoot = newType.getHeapType ().getDepth ();
204
207
205
208
// Note the global's information, if we started as a global. In that case, the
206
209
// code below will refine our type but we can remain a global, which we will
@@ -210,38 +213,21 @@ void PossibleContents::intersect(const PossibleContents& other) {
210
213
globalName = getGlobal ();
211
214
}
212
215
213
- // By assumption |other| has full depth. Consider the other cone in |this|.
214
- if (hasFullCone ()) {
216
+ if (hasFullCone () && other.hasFullCone ()) {
215
217
// Both are full cones, so the result is as well.
216
- value = FullConeType (newType);
218
+ value = DefaultConeType (newType);
217
219
} else {
218
- // The result is a partial cone. If the cone starts in |otherHeapType| then
219
- // we need to adjust the depth down, since it will be smaller than the
220
- // original cone:
221
- /*
222
- // ..
223
- // /
224
- // otherHeapType
225
- // / \
226
- // heapType ..
227
- // \
228
- */
229
- // E.g. if |this| is a cone of depth 10, and |otherHeapType| is an immediate
230
- // subtype of |this|, then the new cone must be of depth 9.
231
- auto newDepth = getCone ().depth ;
232
- if (newType.getHeapType () == otherHeapType) {
233
- assert (depthFromRoot <= otherDepthFromRoot);
234
- auto reduction = otherDepthFromRoot - depthFromRoot;
235
- if (reduction > newDepth) {
236
- // The cone on heapType does not even reach the cone on otherHeapType,
237
- // so the result is not a cone.
238
- setNoneOrNull ();
239
- return ;
240
- }
241
- newDepth -= reduction;
220
+ // The result is a partial cone. Check whether the cones overlap, and if
221
+ // they do, find the new depth.
222
+ if (newDepthFromRoot - depthFromRoot > getCone ().depth ||
223
+ newDepthFromRoot - otherDepthFromRoot > other.getCone ().depth ) {
224
+ setNoneOrNull ();
225
+ return ;
242
226
}
243
-
244
- value = ConeType{newType, newDepth};
227
+ Index newDepth = getCone ().depth - (newDepthFromRoot - depthFromRoot);
228
+ Index otherNewDepth =
229
+ other.getCone ().depth - (newDepthFromRoot - otherDepthFromRoot);
230
+ value = ConeType{newType, std::min (newDepth, otherNewDepth)};
245
231
}
246
232
247
233
if (globalName) {
@@ -371,7 +357,19 @@ bool PossibleContents::isSubContents(const PossibleContents& a,
371
357
return false ;
372
358
}
373
359
374
- WASM_UNREACHABLE (" unhandled case of isSubContents" );
360
+ if (b.isGlobal ()) {
361
+ // We've already ruled out anything but another global or non-full cone type
362
+ // for a.
363
+ return false ;
364
+ }
365
+
366
+ assert (b.isConeType () && (a.isConeType () || a.isGlobal ()));
367
+ if (!Type::isSubType (a.getType (), b.getType ())) {
368
+ return false ;
369
+ }
370
+ // Check that a's cone type is enclosed in b's cone type.
371
+ return a.getType ().getHeapType ().getDepth () + a.getCone ().depth <=
372
+ b.getType ().getHeapType ().getDepth () + b.getCone ().depth ;
375
373
}
376
374
377
375
namespace {
@@ -1463,7 +1461,7 @@ class TNHOracle : public ModuleUtils::ParallelFunctionAnalysis<TNHInfo> {
1463
1461
1464
1462
// Get the type we inferred was possible at a location.
1465
1463
PossibleContents getContents (Expression* curr) {
1466
- auto naiveContents = PossibleContents::fullConeType (curr->type );
1464
+ auto naiveContents = PossibleContents::coneType (curr->type );
1467
1465
1468
1466
// If we inferred nothing, use the naive type.
1469
1467
auto iter = inferences.find (curr);
@@ -1871,8 +1869,8 @@ void TNHOracle::optimizeCallCasts(Expression* call,
1871
1869
// There are two constraints on this location: any value there must
1872
1870
// be of the declared type (curr->type) and also the cast type, so
1873
1871
// we know only their intersection can appear here.
1874
- auto declared = PossibleContents::fullConeType (curr->type );
1875
- auto intersection = PossibleContents::fullConeType (castType);
1872
+ auto declared = PossibleContents::coneType (curr->type );
1873
+ auto intersection = PossibleContents::coneType (castType);
1876
1874
intersection.intersect (declared);
1877
1875
if (intersection.isConeType ()) {
1878
1876
auto intersectionType = intersection.getType ();
@@ -1956,7 +1954,7 @@ struct Flower {
1956
1954
PossibleContents getTNHContents (Expression* curr) {
1957
1955
if (!tnhOracle) {
1958
1956
// No oracle; just use the type in the IR.
1959
- return PossibleContents::fullConeType (curr->type );
1957
+ return PossibleContents::coneType (curr->type );
1960
1958
}
1961
1959
return tnhOracle->getContents (curr);
1962
1960
}
@@ -2858,7 +2856,7 @@ void Flower::readFromData(Type declaredType,
2858
2856
#ifndef NDEBUG
2859
2857
// We must not have anything in the reference that is invalid for the wasm
2860
2858
// type there.
2861
- auto maximalContents = PossibleContents::fullConeType (declaredType);
2859
+ auto maximalContents = PossibleContents::coneType (declaredType);
2862
2860
assert (PossibleContents::isSubContents (refContents, maximalContents));
2863
2861
#endif
2864
2862
@@ -2953,7 +2951,7 @@ void Flower::writeToData(Expression* ref, Expression* value, Index fieldIndex) {
2953
2951
#ifndef NDEBUG
2954
2952
// We must not have anything in the reference that is invalid for the wasm
2955
2953
// type there.
2956
- auto maximalContents = PossibleContents::fullConeType (ref->type );
2954
+ auto maximalContents = PossibleContents::coneType (ref->type );
2957
2955
assert (PossibleContents::isSubContents (refContents, maximalContents));
2958
2956
#endif
2959
2957
0 commit comments