Skip to content

Commit 5422f9a

Browse files
authored
Merge pull request #68233 from tshortli/lazier-sil-optimizer-analysis
SILOptimizer: Make some analysis caches lazy
2 parents 16d7ba0 + 255d5d4 commit 5422f9a

File tree

5 files changed

+38
-29
lines changed

5 files changed

+38
-29
lines changed

include/swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,10 @@ class ClassDecl;
2727
class ClassHierarchyAnalysis : public SILAnalysis {
2828
public:
2929
typedef SmallVector<ClassDecl *, 8> ClassList;
30-
typedef SmallPtrSet<ClassDecl *, 32> ClassSet;
31-
typedef SmallVector<NominalTypeDecl *, 8> NominalTypeList;
32-
typedef llvm::DenseMap<ProtocolDecl *, NominalTypeList>
33-
ProtocolImplementations;
30+
typedef llvm::DenseMap<ClassDecl *, ClassList> ClassListMap;
3431

3532
ClassHierarchyAnalysis(SILModule *Mod)
36-
: SILAnalysis(SILAnalysisKind::ClassHierarchy), M(Mod) {
37-
init();
38-
}
33+
: SILAnalysis(SILAnalysisKind::ClassHierarchy), M(Mod) {}
3934

4035
~ClassHierarchyAnalysis();
4136

@@ -65,7 +60,8 @@ class ClassHierarchyAnalysis : public SILAnalysis {
6560
/// Returns a list of the known direct subclasses of a class \p C in
6661
/// the current module.
6762
const ClassList &getDirectSubClasses(ClassDecl *C) {
68-
return DirectSubclassesCache[C];
63+
populateDirectSubclassesCacheIfNecessary();
64+
return (*DirectSubclassesCache)[C];
6965
}
7066

7167
/// Returns a list of the known indirect subclasses of a class \p C in
@@ -81,7 +77,8 @@ class ClassHierarchyAnalysis : public SILAnalysis {
8177

8278
/// Returns true if the class is inherited by another class in this module.
8379
bool hasKnownDirectSubclasses(ClassDecl *C) {
84-
return DirectSubclassesCache.count(C);
80+
populateDirectSubclassesCacheIfNecessary();
81+
return DirectSubclassesCache->count(C);
8582
}
8683

8784
/// Returns true if the class is indirectly inherited by another class
@@ -92,18 +89,19 @@ class ClassHierarchyAnalysis : public SILAnalysis {
9289
}
9390

9491
private:
95-
/// Compute inheritance properties.
96-
void init();
9792
void getIndirectSubClasses(ClassDecl *Base,
9893
ClassList &IndirectSubs);
9994
/// The module
10095
SILModule *M;
10196

10297
/// A cache that maps a class to all of its known direct subclasses.
103-
llvm::DenseMap<ClassDecl*, ClassList> DirectSubclassesCache;
98+
llvm::Optional<ClassListMap> DirectSubclassesCache;
10499

105100
/// A cache that maps a class to all of its known indirect subclasses.
106-
llvm::DenseMap<ClassDecl*, ClassList> IndirectSubclassesCache;
101+
ClassListMap IndirectSubclassesCache;
102+
103+
/// Populates `DirectSubclassesCache` if necessary.
104+
void populateDirectSubclassesCacheIfNecessary();
107105
};
108106

109107
}

include/swift/SILOptimizer/Analysis/ProtocolConformanceAnalysis.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ class ProtocolConformanceAnalysis : public SILAnalysis {
3939
SoleConformingTypeMap;
4040

4141
ProtocolConformanceAnalysis(SILModule *Mod)
42-
: SILAnalysis(SILAnalysisKind::ProtocolConformance), M(Mod) {
43-
init();
44-
}
42+
: SILAnalysis(SILAnalysisKind::ProtocolConformance), M(Mod) {}
4543

4644
~ProtocolConformanceAnalysis();
4745

@@ -66,14 +64,15 @@ class ProtocolConformanceAnalysis : public SILAnalysis {
6664
virtual void invalidateFunctionTables() override {}
6765

6866
/// Get the nominal types that implement a protocol.
69-
ArrayRef<NominalTypeDecl *> getConformances(const ProtocolDecl *P) const {
70-
auto ConformsListIt = ProtocolConformanceCache.find(P);
71-
return ConformsListIt != ProtocolConformanceCache.end()
67+
ArrayRef<NominalTypeDecl *> getConformances(const ProtocolDecl *P) {
68+
populateConformanceCacheIfNecessary();
69+
auto ConformsListIt = ProtocolConformanceCache->find(P);
70+
return ConformsListIt != ProtocolConformanceCache->end()
7271
? ArrayRef<NominalTypeDecl *>(ConformsListIt->second.begin(),
7372
ConformsListIt->second.end())
7473
: ArrayRef<NominalTypeDecl *>();
7574
}
76-
75+
7776
/// Traverse ProtocolConformanceMapCache recursively to determine sole
7877
/// conforming concrete type.
7978
NominalTypeDecl *findSoleConformingType(ProtocolDecl *Protocol);
@@ -83,17 +82,17 @@ class ProtocolConformanceAnalysis : public SILAnalysis {
8382
bool getSoleConformingType(ProtocolDecl *Protocol, ClassHierarchyAnalysis *CHA, CanType &ConcreteType);
8483

8584
private:
86-
/// Compute inheritance properties.
87-
void init();
88-
8985
/// The module.
9086
SILModule *M;
9187

9288
/// A cache that maps a protocol to its conformances.
93-
ProtocolConformanceMap ProtocolConformanceCache;
89+
llvm::Optional<ProtocolConformanceMap> ProtocolConformanceCache;
9490

9591
/// A cache that holds SoleConformingType for protocols.
9692
SoleConformingTypeMap SoleConformingTypeCache;
93+
94+
/// Populates `ProtocolConformanceCache` if necessary.
95+
void populateConformanceCacheIfNecessary();
9796
};
9897

9998
} // namespace swift

lib/AST/FrontendSourceFileDepGraphFactory.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ static std::string identifierForContext(const DeclContext *DC) {
6767

6868
const auto *ext = cast<ExtensionDecl>(DC);
6969
auto fp = ext->getBodyFingerprint().value_or(Fingerprint::ZERO());
70-
auto typeStr = Mangler.mangleTypeAsContextUSR(ext->getExtendedNominal());
70+
const auto *nominal = ext->getExtendedNominal();
71+
auto typeStr = nominal ? Mangler.mangleTypeAsContextUSR(nominal) : "";
7172
return (typeStr + "@" + fp.getRawValue()).str();
7273
}
7374

lib/SILOptimizer/Analysis/ClassHierarchyAnalysis.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@
1919

2020
using namespace swift;
2121

22-
void ClassHierarchyAnalysis::init() {
22+
// FIXME: This could be implemented as a request.
23+
void ClassHierarchyAnalysis::populateDirectSubclassesCacheIfNecessary() {
24+
if (DirectSubclassesCache.has_value())
25+
return;
26+
27+
DirectSubclassesCache.emplace();
28+
2329
auto module = M->getSwiftModule();
2430

2531
// For each class declaration in our V-table list:
@@ -42,7 +48,7 @@ void ClassHierarchyAnalysis::init() {
4248
// Find the superclass's list of direct subclasses. If it's non-empty,
4349
// we've previously walked up to the class, so there's no reason to keep
4450
// walking from this point.
45-
auto &list = DirectSubclassesCache[super];
51+
auto &list = (*DirectSubclassesCache)[super];
4652
bool shouldVisitSuper = list.empty();
4753

4854
// Check whether C is already in the list, which can happen

lib/SILOptimizer/Analysis/ProtocolConformanceAnalysis.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,12 @@ class NominalTypeWalker : public ASTWalker {
7070
};
7171
} // end anonymous namespace
7272

73-
void ProtocolConformanceAnalysis::init() {
73+
// FIXME: This could be implemented as a request.
74+
void ProtocolConformanceAnalysis::populateConformanceCacheIfNecessary() {
75+
if (ProtocolConformanceCache.has_value())
76+
return;
77+
78+
ProtocolConformanceCache.emplace();
7479

7580
// We only do this in Whole-Module compilation mode.
7681
if (!M->isWholeModule())
@@ -84,7 +89,7 @@ void ProtocolConformanceAnalysis::init() {
8489

8590
/// This operation is quadratic and should only be performed
8691
/// in whole module compilation!
87-
NominalTypeWalker Walker(ProtocolConformanceCache);
92+
NominalTypeWalker Walker(*ProtocolConformanceCache);
8893
for (auto *D : Decls) {
8994
D->walk(Walker);
9095
}

0 commit comments

Comments
 (0)