Skip to content

Commit 112d1bd

Browse files
committed
SILOptimizer: Small cleanups for devirtualizer
Where possible, pass around a ClassDecl or a CanType instead of a SILType that might wrap a metatype; the unwrapping logic was repeated in several places. Also add a FIXME for a bug I found by inspection.
1 parent c970cae commit 112d1bd

File tree

5 files changed

+88
-92
lines changed

5 files changed

+88
-92
lines changed

include/swift/SILOptimizer/Utils/Devirtualize.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class Emitter;
4444
/// \p Subs a container to be used for storing the set of subclasses
4545
void getAllSubclasses(ClassHierarchyAnalysis *CHA,
4646
ClassDecl *CD,
47-
SILType ClassType,
47+
CanType ClassType,
4848
SILModule &M,
4949
ClassHierarchyAnalysis::ClassList &Subs);
5050

@@ -69,18 +69,19 @@ ApplySite tryDevirtualizeApply(ApplySite AI,
6969
ClassHierarchyAnalysis *CHA,
7070
OptRemark::Emitter *ORE = nullptr);
7171
bool canDevirtualizeApply(FullApplySite AI, ClassHierarchyAnalysis *CHA);
72-
bool isNominalTypeWithUnboundGenericParameters(SILType Ty, SILModule &M);
73-
bool canDevirtualizeClassMethod(FullApplySite AI, SILType ClassInstanceType,
72+
bool canDevirtualizeClassMethod(FullApplySite AI, ClassDecl *CD,
7473
OptRemark::Emitter *ORE = nullptr,
7574
bool isEffectivelyFinalMethod = false);
76-
SILFunction *getTargetClassMethod(SILModule &M, SILType ClassOrMetatypeType,
75+
SILFunction *getTargetClassMethod(SILModule &M, ClassDecl *CD,
7776
MethodInst *MI);
77+
CanType getSelfInstanceType(CanType ClassOrMetatypeType);
7878

7979
/// Devirtualize the given apply site, which is known to be devirtualizable.
8080
///
8181
/// The caller must call deleteDevirtualizedApply on the original apply site.
8282
FullApplySite devirtualizeClassMethod(FullApplySite AI,
8383
SILValue ClassInstance,
84+
ClassDecl *CD,
8485
OptRemark::Emitter *ORE);
8586

8687
/// Attempt to devirtualize the given apply site, which is known to be
@@ -89,7 +90,9 @@ FullApplySite devirtualizeClassMethod(FullApplySite AI,
8990
/// If this succeeds, the caller must call deleteDevirtualizedApply on
9091
/// the original apply site.
9192
FullApplySite
92-
tryDevirtualizeClassMethod(FullApplySite AI, SILValue ClassInstance,
93+
tryDevirtualizeClassMethod(FullApplySite AI,
94+
SILValue ClassInstance,
95+
ClassDecl *CD,
9396
OptRemark::Emitter *ORE,
9497
bool isEffectivelyFinalMethod = false);
9598

lib/SILOptimizer/Mandatory/DiagnoseInfiniteRecursion.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ static bool hasRecursiveCallInPath(SILBasicBlock &Block,
5757

5858
auto &M = FAI.getModule();
5959
if (auto *CMI = dyn_cast<ClassMethodInst>(FAI.getCallee())) {
60-
auto ClassType = CMI->getOperand()->getType();
60+
auto ClassType = CMI->getOperand()->getType().getASTType();
6161

6262
// FIXME: If we're not inside the module context of the method,
6363
// we may have to deserialize vtables. If the serialized tables
@@ -66,12 +66,12 @@ static bool hasRecursiveCallInPath(SILBasicBlock &Block,
6666
// Though, this has the added bonus of not looking into vtables
6767
// outside the current module. Because we're not doing IPA, let
6868
// alone cross-module IPA, this is all well and good.
69-
auto *BGC = ClassType.getNominalOrBoundGenericNominal();
70-
if (BGC && BGC->getModuleContext() != TargetModule) {
69+
auto *CD = ClassType.getClassOrBoundGenericClass();
70+
if (CD && CD->getModuleContext() != TargetModule) {
7171
continue;
7272
}
7373

74-
auto *F = getTargetClassMethod(M, ClassType, CMI);
74+
auto *F = getTargetClassMethod(M, CD, CMI);
7575
if (F == Target)
7676
return true;
7777

lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,15 @@ static FullApplySite CloneApply(FullApplySite AI, SILBuilder &Builder) {
118118
/// Insert monomorphic inline caches for a specific class or metatype
119119
/// type \p SubClassTy.
120120
static FullApplySite speculateMonomorphicTarget(FullApplySite AI,
121-
SILType SubType,
121+
CanType SubType,
122+
ClassDecl *CD,
122123
CheckedCastBranchInst *&CCBI) {
123-
CCBI = nullptr;
124-
// Bail if this class_method cannot be devirtualized.
125-
if (!canDevirtualizeClassMethod(AI, SubType))
124+
if (SubType->hasDynamicSelfType())
126125
return FullApplySite();
127126

128-
if (SubType.getASTType()->hasDynamicSelfType())
127+
CCBI = nullptr;
128+
// Bail if this class_method cannot be devirtualized.
129+
if (!canDevirtualizeClassMethod(AI, CD))
129130
return FullApplySite();
130131

131132
// Can't speculate begin_apply yet.
@@ -144,7 +145,9 @@ static FullApplySite speculateMonomorphicTarget(FullApplySite AI,
144145
SILBasicBlock *Iden = F->createBasicBlock();
145146
// Virt is the block containing the slow virtual call.
146147
SILBasicBlock *Virt = F->createBasicBlock();
147-
Iden->createPhiArgument(SubType, ValueOwnershipKind::Owned);
148+
Iden->createPhiArgument(
149+
SILType::getPrimitiveObjectType(SubType),
150+
ValueOwnershipKind::Owned);
148151

149152
SILBasicBlock *Continue = Entry->split(It);
150153

@@ -155,8 +158,10 @@ static FullApplySite speculateMonomorphicTarget(FullApplySite AI,
155158
ClassMethodInst *CMI = cast<ClassMethodInst>(AI.getCallee());
156159

157160
CCBI = Builder.createCheckedCastBranch(AI.getLoc(), /*exact*/ true,
158-
CMI->getOperand(), SubType, Iden,
159-
Virt);
161+
CMI->getOperand(),
162+
SILType::getPrimitiveObjectType(SubType),
163+
Iden,
164+
Virt);
160165
It = CCBI->getIterator();
161166

162167
SILBuilderWithScope VirtBuilder(Virt, AI.getInstruction());
@@ -219,7 +224,7 @@ static FullApplySite speculateMonomorphicTarget(FullApplySite AI,
219224

220225
// Devirtualize the apply instruction on the identical path.
221226
auto NewInst =
222-
devirtualizeClassMethod(IdenAI, DownCastedClassInstance, nullptr);
227+
devirtualizeClassMethod(IdenAI, DownCastedClassInstance, CD, nullptr);
223228
assert(NewInst && "Expected to be able to devirtualize apply!");
224229
(void)NewInst;
225230

@@ -381,21 +386,20 @@ static bool tryToSpeculateTarget(FullApplySite AI, ClassHierarchyAnalysis *CHA,
381386
// with a value whose type is closer (in the class hierarchy) to the
382387
// actual dynamic type.
383388
auto SubTypeValue = stripUpCasts(CMI->getOperand());
384-
SILType SubType = SubTypeValue->getType();
389+
CanType SubType = SubTypeValue->getType().getASTType();
385390

386391
// Bail if any generic types parameters of the class instance type are
387392
// unbound.
388393
// We cannot devirtualize unbound generic calls yet.
389-
if (SubType.hasArchetype())
394+
if (SubType->hasArchetype())
390395
return false;
391396

392-
auto &M = CMI->getModule();
393-
auto ClassType = SubType;
394-
if (SubType.is<MetatypeType>())
395-
ClassType = SubType.getMetatypeInstanceType(M);
397+
auto *F = CMI->getFunction();
398+
auto &M = F->getModule();
396399

397400
CheckedCastBranchInst *LastCCBI = nullptr;
398401

402+
auto ClassType = getSelfInstanceType(SubType);
399403
ClassDecl *CD = ClassType.getClassOrBoundGenericClass();
400404
assert(CD && "Expected decl for class type!");
401405

@@ -404,15 +408,15 @@ static bool tryToSpeculateTarget(FullApplySite AI, ClassHierarchyAnalysis *CHA,
404408
// try to devirtualize it completely.
405409
ClassHierarchyAnalysis::ClassList Subs;
406410
if (isDefaultCaseKnown(CHA, AI, CD, Subs)) {
407-
auto NewInst = tryDevirtualizeClassMethod(AI, SubTypeValue, &ORE);
411+
auto NewInst = tryDevirtualizeClassMethod(AI, SubTypeValue, CD, &ORE);
408412
if (NewInst)
409413
deleteDevirtualizedApply(AI);
410414
return bool(NewInst);
411415
}
412416

413417
LLVM_DEBUG(llvm::dbgs() << "Inserting monomorphic speculative call for "
414418
"class " << CD->getName() << "\n");
415-
return !!speculateMonomorphicTarget(AI, SubType, LastCCBI);
419+
return !!speculateMonomorphicTarget(AI, SubType, CD, LastCCBI);
416420
}
417421

418422
// True if any instructions were changed or generated.
@@ -438,7 +442,7 @@ static bool tryToSpeculateTarget(FullApplySite AI, ClassHierarchyAnalysis *CHA,
438442

439443
// Try to devirtualize the static class of instance
440444
// if it is possible.
441-
if (auto F = getTargetClassMethod(M, SubType, CMI)) {
445+
if (auto F = getTargetClassMethod(M, CD, CMI)) {
442446
// Do not devirtualize if a method in the base class is marked
443447
// as non-optimizable. This way it is easy to disable the
444448
// devirtualization of this method in the base class and
@@ -447,7 +451,7 @@ static bool tryToSpeculateTarget(FullApplySite AI, ClassHierarchyAnalysis *CHA,
447451
return false;
448452
}
449453

450-
auto FirstAI = speculateMonomorphicTarget(AI, SubType, LastCCBI);
454+
auto FirstAI = speculateMonomorphicTarget(AI, SubType, CD, LastCCBI);
451455
if (FirstAI) {
452456
Changed = true;
453457
AI = FirstAI;
@@ -501,18 +505,15 @@ static bool tryToSpeculateTarget(FullApplySite AI, ClassHierarchyAnalysis *CHA,
501505
}
502506

503507
CanType CanClassType = S->getDeclaredInterfaceType()->getCanonicalType();
504-
SILType ClassType = SILType::getPrimitiveObjectType(CanClassType);
505-
506-
auto ClassOrMetatypeType = ClassType;
507-
if (auto EMT = SubType.getAs<AnyMetatypeType>()) {
508-
auto InstTy = ClassType.getASTType();
509-
auto *MetaTy = MetatypeType::get(InstTy, EMT->getRepresentation());
510-
auto CanMetaTy = CanMetatypeType(MetaTy);
511-
ClassOrMetatypeType = SILType::getPrimitiveObjectType(CanMetaTy);
508+
509+
auto ClassOrMetatypeType = CanClassType;
510+
if (auto MT = dyn_cast<MetatypeType>(SubType)) {
511+
ClassOrMetatypeType = CanMetatypeType::get(CanClassType,
512+
MT->getRepresentation());
512513
}
513514

514515
// Pass the metatype of the subclass.
515-
auto NewAI = speculateMonomorphicTarget(AI, ClassOrMetatypeType, LastCCBI);
516+
auto NewAI = speculateMonomorphicTarget(AI, ClassOrMetatypeType, S, LastCCBI);
516517
if (!NewAI) {
517518
NotHandledSubsNum++;
518519
continue;
@@ -567,7 +568,7 @@ static bool tryToSpeculateTarget(FullApplySite AI, ClassHierarchyAnalysis *CHA,
567568
ORE.emit(RB);
568569
return true;
569570
}
570-
auto NewInst = tryDevirtualizeClassMethod(AI, SubTypeValue, nullptr);
571+
auto NewInst = tryDevirtualizeClassMethod(AI, SubTypeValue, CD, nullptr);
571572
if (NewInst) {
572573
ORE.emit(RB);
573574
deleteDevirtualizedApply(AI);

0 commit comments

Comments
 (0)