@@ -225,7 +225,7 @@ static bool isKnownFinalClass(ClassDecl *CD, SILModule &M,
225
225
// can be derived e.g.:
226
226
// - from a constructor or
227
227
// - from a successful outcome of a checked_cast_br [exact] instruction.
228
- static SILValue getInstanceWithExactDynamicType (SILValue S, SILModule &M,
228
+ SILValue swift:: getInstanceWithExactDynamicType (SILValue S, SILModule &M,
229
229
ClassHierarchyAnalysis *CHA) {
230
230
231
231
while (S) {
@@ -268,6 +268,143 @@ static SILValue getInstanceWithExactDynamicType(SILValue S, SILModule &M,
268
268
return SILValue ();
269
269
}
270
270
271
+ // / Try to determine the exact dynamic type of an object.
272
+ // / returns the exact dynamic type of the object, or an empty type if the exact
273
+ // / type could not be determined.
274
+ SILType swift::getExactDynamicType (SILValue S, SILModule &M,
275
+ ClassHierarchyAnalysis *CHA,
276
+ bool ForUnderlyingObject) {
277
+ // Set of values to be checked for their exact types.
278
+ SmallVector<SILValue, 8 > WorkList;
279
+ // The detected type of the underlying object.
280
+ SILType ResultType;
281
+ // Set of processed values.
282
+ llvm::SetVector<SILValue> Processed;
283
+ WorkList.push_back (S);
284
+
285
+ while (!WorkList.empty ()) {
286
+ auto V = WorkList.pop_back_val ();
287
+ if (!V)
288
+ return SILType ();
289
+ if (Processed.count (V))
290
+ continue ;
291
+ Processed.insert (V);
292
+ // For underlying object strip casts and projections.
293
+ // For the object itself, simply strip casts.
294
+ V = ForUnderlyingObject ? getUnderlyingObject (V) : stripCasts (V);
295
+
296
+ if (isa<AllocRefInst>(V) || isa<MetatypeInst>(V)) {
297
+ if (ResultType && ResultType != V->getType ())
298
+ return SILType ();
299
+ ResultType = V->getType ();
300
+ continue ;
301
+ }
302
+
303
+ if (isa<LiteralInst>(V)) {
304
+ if (ResultType && ResultType != V->getType ())
305
+ return SILType ();
306
+ ResultType = V->getType ();
307
+ continue ;
308
+ }
309
+
310
+ if (isa<StructInst>(V) || isa<TupleInst>(V) || isa<EnumInst>(V)) {
311
+ if (ResultType && ResultType != V->getType ())
312
+ return SILType ();
313
+ ResultType = V->getType ();
314
+ continue ;
315
+ }
316
+
317
+ if (ForUnderlyingObject) {
318
+ if (isa<AllocationInst>(V)) {
319
+ if (ResultType && ResultType != V->getType ())
320
+ return SILType ();
321
+ ResultType = V->getType ();
322
+ continue ;
323
+ }
324
+ // Look through strong_pin instructions.
325
+ if (isa<StrongPinInst>(V)) {
326
+ WorkList.push_back (cast<SILInstruction>(V)->getOperand (0 ));
327
+ continue ;
328
+ }
329
+ }
330
+
331
+ auto Arg = dyn_cast<SILArgument>(V);
332
+ if (!Arg) {
333
+ // We don't know what it is.
334
+ return SILType ();
335
+ }
336
+
337
+ if (Arg->isFunctionArg ()) {
338
+ // Bail on metatypes for now.
339
+ if (Arg->getType ().getSwiftRValueType ()->is <AnyMetatypeType>()) {
340
+ return SILType ();
341
+ }
342
+ auto *CD = Arg->getType ().getClassOrBoundGenericClass ();
343
+ // If it is not class and it is a trivial type, then it
344
+ // should be the exact type.
345
+ if (!CD && Arg->getType ().isTrivial (M)) {
346
+ if (ResultType && ResultType != Arg->getType ())
347
+ return SILType ();
348
+ ResultType = Arg->getType ();
349
+ continue ;
350
+ }
351
+
352
+ if (!CD) {
353
+ // It is not a class or a trivial type, so we don't know what it is.
354
+ return SILType ();
355
+ }
356
+
357
+ // Check if this class is effectively final.
358
+ if (!isKnownFinalClass (CD, M, CHA)) {
359
+ return SILType ();
360
+ }
361
+
362
+ if (ResultType && ResultType != Arg->getType ())
363
+ return SILType ();
364
+ ResultType = Arg->getType ();
365
+ continue ;
366
+ }
367
+
368
+ auto *SinglePred = Arg->getParent ()->getSinglePredecessor ();
369
+ if (SinglePred) {
370
+ // If it is a BB argument received on a success branch
371
+ // of a checked_cast_br, then we know its exact type.
372
+ auto *CCBI = dyn_cast<CheckedCastBranchInst>(SinglePred->getTerminator ());
373
+ if (CCBI && CCBI->isExact () && CCBI->getSuccessBB () == Arg->getParent ()) {
374
+ if (ResultType && ResultType != Arg->getType ())
375
+ return SILType ();
376
+ ResultType = Arg->getType ();
377
+ continue ;
378
+ }
379
+ }
380
+
381
+ // It is a BB argument, look through incoming values. If they all have the
382
+ // same exact type, then we consider it to be the type of the BB argument.
383
+ SmallVector<SILValue, 4 > IncomingValues;
384
+
385
+ if (Arg->getIncomingValues (IncomingValues)) {
386
+ for (auto InValue : IncomingValues) {
387
+ WorkList.push_back (InValue);
388
+ }
389
+ continue ;
390
+ }
391
+
392
+ // The exact type is unknown.
393
+ return SILType ();
394
+ }
395
+
396
+ return ResultType;
397
+ }
398
+
399
+
400
+ // / Try to determine the exact dynamic type of the underlying object.
401
+ // / returns the exact dynamic type of a value, or an empty type if the exact
402
+ // / type could not be determined.
403
+ SILType
404
+ swift::getExactDynamicTypeOfUnderlyingObject (SILValue S, SILModule &M,
405
+ ClassHierarchyAnalysis *CHA) {
406
+ return getExactDynamicType (S, M, CHA, /* ForUnderlyingObject */ true );
407
+ }
271
408
272
409
// Start with the substitutions from the apply.
273
410
// Try to propagate them to find out the real substitutions required
@@ -873,6 +1010,12 @@ swift::tryDevirtualizeApply(FullApplySite AI, ClassHierarchyAnalysis *CHA) {
873
1010
CMI->getModule (),
874
1011
CHA))
875
1012
return tryDevirtualizeClassMethod (AI, Instance);
1013
+
1014
+ if (auto ExactTy = getExactDynamicType (CMI->getOperand (), CMI->getModule (),
1015
+ CHA)) {
1016
+ if (ExactTy == CMI->getOperand ()->getType ())
1017
+ return tryDevirtualizeClassMethod (AI, CMI->getOperand ());
1018
+ }
876
1019
}
877
1020
878
1021
if (isa<SuperMethodInst>(AI.getCallee ())) {
0 commit comments