Skip to content

Commit e096b2f

Browse files
committed
BasicCalleeAnalysis: make the callee list datastructure more efficient
This avoids copying a SmallVector in case of multiple callees in the list. Instead, just reference the callee list in the cache.
1 parent 20c63cc commit e096b2f

File tree

2 files changed

+59
-15
lines changed

2 files changed

+59
-15
lines changed

include/swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,38 +37,73 @@ class SILWitnessTable;
3737
/// allows a client to determine whether the list is incomplete in the
3838
/// sense that there may be unrepresented callees.
3939
class CalleeList {
40-
llvm::TinyPtrVector<SILFunction *> CalleeFunctions;
41-
bool IsIncomplete;
40+
friend class CalleeCache;
41+
42+
using Callees = llvm::SmallVector<SILFunction *, 16>;
43+
44+
void *functionOrCallees;
45+
46+
enum class Kind : uint8_t {
47+
empty,
48+
singleFunction,
49+
multipleCallees
50+
} kind;
51+
52+
bool incomplete;
53+
54+
CalleeList(void *ptr, Kind kind, bool isIncomplete) :
55+
functionOrCallees(ptr), kind(kind), incomplete(isIncomplete) {}
4256

4357
public:
4458
/// Constructor for when we know nothing about the callees and must
4559
/// assume the worst.
46-
CalleeList() : IsIncomplete(true) {}
60+
CalleeList() : CalleeList(nullptr, Kind::empty, /*incomplete*/ true) {}
4761

4862
/// Constructor for the case where we know an apply can target only
4963
/// a single function.
50-
CalleeList(SILFunction *F) : CalleeFunctions(F), IsIncomplete(false) {}
64+
CalleeList(SILFunction *F)
65+
: CalleeList(F, Kind::singleFunction, /*incomplete*/ false) {}
5166

5267
/// Constructor for arbitrary lists of callees.
53-
CalleeList(llvm::SmallVectorImpl<SILFunction *> &List, bool IsIncomplete)
54-
: CalleeFunctions(llvm::makeArrayRef(List.begin(), List.end())),
55-
IsIncomplete(IsIncomplete) {}
68+
CalleeList(Callees *callees, bool IsIncomplete)
69+
: CalleeList(callees, Kind::multipleCallees, IsIncomplete) {}
70+
71+
static CalleeList fromOpaque(void *ptr, unsigned char kind, unsigned char isComplete) {
72+
return CalleeList(ptr, (Kind)kind, (bool)isComplete);
73+
}
74+
75+
void *getOpaquePtr() const { return functionOrCallees; }
76+
unsigned char getOpaqueKind() const { return (unsigned char)kind; }
5677

5778
SWIFT_DEBUG_DUMP;
5879

5980
void print(llvm::raw_ostream &os) const;
6081

6182
/// Return an iterator for the beginning of the list.
6283
ArrayRef<SILFunction *>::iterator begin() const {
63-
return CalleeFunctions.begin();
84+
switch (kind) {
85+
case Kind::empty:
86+
return nullptr;
87+
case Kind::singleFunction:
88+
return (SILFunction * const *)&functionOrCallees;
89+
case Kind::multipleCallees:
90+
return ((Callees *)functionOrCallees)->begin();
91+
}
6492
}
6593

6694
/// Return an iterator for the end of the list.
6795
ArrayRef<SILFunction *>::iterator end() const {
68-
return CalleeFunctions.end();
96+
switch (kind) {
97+
case Kind::empty:
98+
return nullptr;
99+
case Kind::singleFunction:
100+
return (SILFunction * const *)&functionOrCallees + 1;
101+
case Kind::multipleCallees:
102+
return ((Callees *)functionOrCallees)->end();
103+
}
69104
}
70105

71-
bool isIncomplete() const { return IsIncomplete; }
106+
bool isIncomplete() const { return incomplete; }
72107

73108
/// Returns true if all callees are known and not external.
74109
bool allCalleesVisible() const;
@@ -80,14 +115,13 @@ class CalleeList {
80115
/// any function application site (including those that are simple
81116
/// function_ref, thin_to_thick, or partial_apply callees).
82117
class CalleeCache {
83-
using Callees = llvm::SmallVector<SILFunction *, 16>;
84-
using CalleesAndCanCallUnknown = llvm::PointerIntPair<Callees *, 1>;
118+
using CalleesAndCanCallUnknown = llvm::PointerIntPair<CalleeList::Callees *, 1>;
85119
using CacheType = llvm::DenseMap<SILDeclRef, CalleesAndCanCallUnknown>;
86120

87121
SILModule &M;
88122

89123
// Allocator for the SmallVectors that we will be allocating.
90-
llvm::SpecificBumpPtrAllocator<Callees> Allocator;
124+
llvm::SpecificBumpPtrAllocator<CalleeList::Callees> Allocator;
91125

92126
// The cache of precomputed callee lists for function decls appearing
93127
// in class virtual dispatch tables and witness tables.
@@ -106,6 +140,11 @@ class CalleeCache {
106140
/// Return the list of callees that can potentially be called at the
107141
/// given apply site.
108142
CalleeList getCalleeList(FullApplySite FAS) const;
143+
144+
CalleeList getCalleeListOfValue(SILValue callee) const {
145+
return getCalleeListForCalleeKind(callee);
146+
}
147+
109148
/// Return the list of callees that can potentially be called at the
110149
/// given instruction. E.g. it could be destructors.
111150
CalleeList getCalleeList(SILInstruction *I) const;
@@ -180,6 +219,11 @@ class BasicCalleeAnalysis : public SILAnalysis {
180219
return Cache->getCalleeList(FAS);
181220
}
182221

222+
CalleeList getCalleeListOfValue(SILValue callee) {
223+
updateCache();
224+
return Cache->getCalleeListOfValue(callee);
225+
}
226+
183227
CalleeList getCalleeList(SILInstruction *I) {
184228
updateCache();
185229
return Cache->getCalleeList(I);

lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ CalleeCache::getOrCreateCalleesForMethod(SILDeclRef Decl) {
8585
if (Found != TheCache.end())
8686
return Found->second;
8787

88-
auto *TheCallees = new (Allocator.Allocate()) Callees;
88+
auto *TheCallees = new (Allocator.Allocate()) CalleeList::Callees;
8989

9090
bool canCallUnknown = !calleesAreStaticallyKnowable(M, Decl);
9191
CalleesAndCanCallUnknown Entry(TheCallees, canCallUnknown);
@@ -225,7 +225,7 @@ CalleeList CalleeCache::getCalleeList(SILDeclRef Decl) const {
225225
return CalleeList();
226226

227227
auto &Pair = Found->second;
228-
return CalleeList(*Pair.getPointer(), Pair.getInt());
228+
return CalleeList(Pair.getPointer(), Pair.getInt());
229229
}
230230

231231
// Return a callee list for the given witness method.

0 commit comments

Comments
 (0)