Skip to content

Commit df8de5f

Browse files
committed
SILOptimizer: Compute ClassHierarchyAnalysis cache lazily.
When serializing modules with `-experimental-skip-all-function-bodies`, this analysis was eagerly populating a cache that would go unused since there is no optimization to do. With `-experimental-lazy-typecheck`, this work would also trigger unnecessary typechecking requests. NFC.
1 parent f1e3ef8 commit df8de5f

File tree

2 files changed

+18
-15
lines changed

2 files changed

+18
-15
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
}

lib/SILOptimizer/Analysis/ClassHierarchyAnalysis.cpp

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

2020
using namespace swift;
2121

22-
void ClassHierarchyAnalysis::init() {
22+
void ClassHierarchyAnalysis::populateDirectSubclassesCacheIfNecessary() {
23+
if (DirectSubclassesCache.has_value())
24+
return;
25+
26+
DirectSubclassesCache.emplace();
27+
2328
auto module = M->getSwiftModule();
2429

2530
// For each class declaration in our V-table list:
@@ -42,7 +47,7 @@ void ClassHierarchyAnalysis::init() {
4247
// Find the superclass's list of direct subclasses. If it's non-empty,
4348
// we've previously walked up to the class, so there's no reason to keep
4449
// walking from this point.
45-
auto &list = DirectSubclassesCache[super];
50+
auto &list = (*DirectSubclassesCache)[super];
4651
bool shouldVisitSuper = list.empty();
4752

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

0 commit comments

Comments
 (0)