Skip to content

Commit 6a28452

Browse files
committed
move CalleeCache from SILOptimizer to SIL
Extract the CalleeCache from BasicCalleeAnalysis so that it can be used in SIL without BasicCalleeAnalysis
1 parent 286fdd9 commit 6a28452

File tree

10 files changed

+553
-505
lines changed

10 files changed

+553
-505
lines changed

include/swift/SIL/CalleeCache.h

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
//===- CalleeCache.h - Determine callees per call site ----------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_UTILS_CALLEECACHE_H
14+
#define SWIFT_UTILS_CALLEECACHE_H
15+
16+
#include "swift/SIL/ApplySite.h"
17+
#include "swift/SIL/SILDeclRef.h"
18+
#include "llvm/ADT/ArrayRef.h"
19+
#include "llvm/ADT/DenseMap.h"
20+
#include "llvm/ADT/PointerIntPair.h"
21+
#include "llvm/ADT/SmallVector.h"
22+
#include "llvm/Support/Allocator.h"
23+
24+
namespace swift {
25+
26+
class SILFunction;
27+
class SILModule;
28+
class SILWitnessTable;
29+
class ValueDecl;
30+
31+
/// Do we have enough information to determine all callees that could
32+
/// be reached by calling the function represented by Decl?
33+
bool calleesAreStaticallyKnowable(SILModule &module, SILDeclRef decl);
34+
35+
/// Do we have enough information to determine all callees that could
36+
/// be reached by calling the function represented by Decl?
37+
bool calleesAreStaticallyKnowable(SILModule &module, ValueDecl *vd);
38+
39+
/// CalleeList is a data structure representing the list of potential
40+
/// callees at a particular apply site. It also has a query that
41+
/// allows a client to determine whether the list is incomplete in the
42+
/// sense that there may be unrepresented callees.
43+
class CalleeList {
44+
friend class CalleeCache;
45+
46+
using Callees = llvm::SmallVector<SILFunction *, 16>;
47+
48+
void *functionOrCallees;
49+
50+
enum class Kind : uint8_t {
51+
empty,
52+
singleFunction,
53+
multipleCallees
54+
} kind;
55+
56+
bool incomplete;
57+
58+
CalleeList(void *ptr, Kind kind, bool isIncomplete) :
59+
functionOrCallees(ptr), kind(kind), incomplete(isIncomplete) {}
60+
61+
public:
62+
/// Constructor for when we know nothing about the callees and must
63+
/// assume the worst.
64+
CalleeList() : CalleeList(nullptr, Kind::empty, /*incomplete*/ true) {}
65+
66+
/// Constructor for the case where we know an apply can target only
67+
/// a single function.
68+
CalleeList(SILFunction *F)
69+
: CalleeList(F, Kind::singleFunction, /*incomplete*/ false) {}
70+
71+
/// Constructor for arbitrary lists of callees.
72+
CalleeList(Callees *callees, bool IsIncomplete)
73+
: CalleeList(callees, Kind::multipleCallees, IsIncomplete) {}
74+
75+
static CalleeList fromOpaque(void *ptr, unsigned char kind, unsigned char isComplete) {
76+
return CalleeList(ptr, (Kind)kind, (bool)isComplete);
77+
}
78+
79+
void *getOpaquePtr() const { return functionOrCallees; }
80+
unsigned char getOpaqueKind() const { return (unsigned char)kind; }
81+
82+
SWIFT_DEBUG_DUMP;
83+
84+
void print(llvm::raw_ostream &os) const;
85+
86+
/// Return an iterator for the beginning of the list.
87+
ArrayRef<SILFunction *>::iterator begin() const {
88+
switch (kind) {
89+
case Kind::empty:
90+
return nullptr;
91+
case Kind::singleFunction:
92+
return (SILFunction * const *)&functionOrCallees;
93+
case Kind::multipleCallees:
94+
return ((Callees *)functionOrCallees)->begin();
95+
}
96+
}
97+
98+
/// Return an iterator for the end of the list.
99+
ArrayRef<SILFunction *>::iterator end() const {
100+
switch (kind) {
101+
case Kind::empty:
102+
return nullptr;
103+
case Kind::singleFunction:
104+
return (SILFunction * const *)&functionOrCallees + 1;
105+
case Kind::multipleCallees:
106+
return ((Callees *)functionOrCallees)->end();
107+
}
108+
}
109+
110+
size_t getCount() const {
111+
switch (kind) {
112+
case Kind::empty: return 0;
113+
case Kind::singleFunction: return 1;
114+
case Kind::multipleCallees: return ((Callees *)functionOrCallees)->size();
115+
}
116+
}
117+
118+
SILFunction *get(unsigned index) const {
119+
switch (kind) {
120+
case Kind::empty: llvm_unreachable("empty callee list");
121+
case Kind::singleFunction: return (SILFunction *)functionOrCallees;
122+
case Kind::multipleCallees: return ((Callees *)functionOrCallees)->operator[](index);
123+
}
124+
}
125+
126+
bool isIncomplete() const { return incomplete; }
127+
128+
/// Returns true if all callees are known and not external.
129+
bool allCalleesVisible() const;
130+
};
131+
132+
/// CalleeCache is a helper class that builds lists of potential
133+
/// callees for class and witness method applications, and provides an
134+
/// interface for retrieving a (possibly incomplete) CalleeList for
135+
/// any function application site (including those that are simple
136+
/// function_ref, thin_to_thick, or partial_apply callees).
137+
class CalleeCache {
138+
using CalleesAndCanCallUnknown = llvm::PointerIntPair<CalleeList::Callees *, 1>;
139+
using CacheType = llvm::DenseMap<SILDeclRef, CalleesAndCanCallUnknown>;
140+
141+
SILModule &M;
142+
143+
// Allocator for the SmallVectors that we will be allocating.
144+
llvm::SpecificBumpPtrAllocator<CalleeList::Callees> Allocator;
145+
146+
// The cache of precomputed callee lists for function decls appearing
147+
// in class virtual dispatch tables and witness tables.
148+
CacheType TheCache;
149+
150+
public:
151+
CalleeCache(SILModule &M) : M(M) {
152+
computeMethodCallees();
153+
sortAndUniqueCallees();
154+
}
155+
156+
~CalleeCache() {
157+
Allocator.DestroyAll();
158+
}
159+
160+
/// Return the list of callees that can potentially be called at the
161+
/// given apply site.
162+
CalleeList getCalleeList(FullApplySite FAS) const;
163+
164+
CalleeList getCalleeListOfValue(SILValue callee) const {
165+
return getCalleeListForCalleeKind(callee);
166+
}
167+
168+
/// Return the list of callees that can potentially be called at the
169+
/// given instruction. E.g. it could be destructors.
170+
CalleeList getDestructors(SILType type, bool isExactType) const;
171+
172+
CalleeList getCalleeList(SILDeclRef Decl) const;
173+
174+
private:
175+
void enumerateFunctionsInModule();
176+
void sortAndUniqueCallees();
177+
CalleesAndCanCallUnknown &getOrCreateCalleesForMethod(SILDeclRef Decl);
178+
void computeClassMethodCallees();
179+
void computeWitnessMethodCalleesForWitnessTable(SILWitnessTable &WT);
180+
void computeMethodCallees();
181+
SILFunction *getSingleCalleeForWitnessMethod(WitnessMethodInst *WMI) const;
182+
CalleeList getCalleeList(WitnessMethodInst *WMI) const;
183+
CalleeList getCalleeList(ClassMethodInst *CMI) const;
184+
CalleeList getCalleeListForCalleeKind(SILValue Callee) const;
185+
};
186+
187+
} // end namespace swift
188+
189+
#endif

include/swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h

Lines changed: 1 addition & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define SWIFT_SILOPTIMIZER_ANALYSIS_BASICCALLEEANALYSIS_H
1515

1616
#include "swift/SILOptimizer/Analysis/Analysis.h"
17+
#include "swift/SIL/CalleeCache.h"
1718
#include "swift/SIL/SILFunction.h"
1819
#include "swift/SIL/SILInstruction.h"
1920
#include "swift/SIL/ApplySite.h"
@@ -27,160 +28,6 @@
2728

2829
namespace swift {
2930

30-
class ClassDecl;
31-
class SILFunction;
32-
class SILModule;
33-
class SILWitnessTable;
34-
class SILPassManager;
35-
36-
/// CalleeList is a data structure representing the list of potential
37-
/// callees at a particular apply site. It also has a query that
38-
/// allows a client to determine whether the list is incomplete in the
39-
/// sense that there may be unrepresented callees.
40-
class CalleeList {
41-
friend class CalleeCache;
42-
43-
using Callees = llvm::SmallVector<SILFunction *, 16>;
44-
45-
void *functionOrCallees;
46-
47-
enum class Kind : uint8_t {
48-
empty,
49-
singleFunction,
50-
multipleCallees
51-
} kind;
52-
53-
bool incomplete;
54-
55-
CalleeList(void *ptr, Kind kind, bool isIncomplete) :
56-
functionOrCallees(ptr), kind(kind), incomplete(isIncomplete) {}
57-
58-
public:
59-
/// Constructor for when we know nothing about the callees and must
60-
/// assume the worst.
61-
CalleeList() : CalleeList(nullptr, Kind::empty, /*incomplete*/ true) {}
62-
63-
/// Constructor for the case where we know an apply can target only
64-
/// a single function.
65-
CalleeList(SILFunction *F)
66-
: CalleeList(F, Kind::singleFunction, /*incomplete*/ false) {}
67-
68-
/// Constructor for arbitrary lists of callees.
69-
CalleeList(Callees *callees, bool IsIncomplete)
70-
: CalleeList(callees, Kind::multipleCallees, IsIncomplete) {}
71-
72-
static CalleeList fromOpaque(void *ptr, unsigned char kind, unsigned char isComplete) {
73-
return CalleeList(ptr, (Kind)kind, (bool)isComplete);
74-
}
75-
76-
void *getOpaquePtr() const { return functionOrCallees; }
77-
unsigned char getOpaqueKind() const { return (unsigned char)kind; }
78-
79-
SWIFT_DEBUG_DUMP;
80-
81-
void print(llvm::raw_ostream &os) const;
82-
83-
/// Return an iterator for the beginning of the list.
84-
ArrayRef<SILFunction *>::iterator begin() const {
85-
switch (kind) {
86-
case Kind::empty:
87-
return nullptr;
88-
case Kind::singleFunction:
89-
return (SILFunction * const *)&functionOrCallees;
90-
case Kind::multipleCallees:
91-
return ((Callees *)functionOrCallees)->begin();
92-
}
93-
}
94-
95-
/// Return an iterator for the end of the list.
96-
ArrayRef<SILFunction *>::iterator end() const {
97-
switch (kind) {
98-
case Kind::empty:
99-
return nullptr;
100-
case Kind::singleFunction:
101-
return (SILFunction * const *)&functionOrCallees + 1;
102-
case Kind::multipleCallees:
103-
return ((Callees *)functionOrCallees)->end();
104-
}
105-
}
106-
107-
size_t getCount() const {
108-
switch (kind) {
109-
case Kind::empty: return 0;
110-
case Kind::singleFunction: return 1;
111-
case Kind::multipleCallees: return ((Callees *)functionOrCallees)->size();
112-
}
113-
}
114-
115-
SILFunction *get(unsigned index) const {
116-
switch (kind) {
117-
case Kind::empty: llvm_unreachable("empty callee list");
118-
case Kind::singleFunction: return (SILFunction *)functionOrCallees;
119-
case Kind::multipleCallees: return ((Callees *)functionOrCallees)->operator[](index);
120-
}
121-
}
122-
123-
bool isIncomplete() const { return incomplete; }
124-
125-
/// Returns true if all callees are known and not external.
126-
bool allCalleesVisible() const;
127-
};
128-
129-
/// CalleeCache is a helper class that builds lists of potential
130-
/// callees for class and witness method applications, and provides an
131-
/// interface for retrieving a (possibly incomplete) CalleeList for
132-
/// any function application site (including those that are simple
133-
/// function_ref, thin_to_thick, or partial_apply callees).
134-
class CalleeCache {
135-
using CalleesAndCanCallUnknown = llvm::PointerIntPair<CalleeList::Callees *, 1>;
136-
using CacheType = llvm::DenseMap<SILDeclRef, CalleesAndCanCallUnknown>;
137-
138-
SILModule &M;
139-
140-
// Allocator for the SmallVectors that we will be allocating.
141-
llvm::SpecificBumpPtrAllocator<CalleeList::Callees> Allocator;
142-
143-
// The cache of precomputed callee lists for function decls appearing
144-
// in class virtual dispatch tables and witness tables.
145-
CacheType TheCache;
146-
147-
public:
148-
CalleeCache(SILModule &M) : M(M) {
149-
computeMethodCallees();
150-
sortAndUniqueCallees();
151-
}
152-
153-
~CalleeCache() {
154-
Allocator.DestroyAll();
155-
}
156-
157-
/// Return the list of callees that can potentially be called at the
158-
/// given apply site.
159-
CalleeList getCalleeList(FullApplySite FAS) const;
160-
161-
CalleeList getCalleeListOfValue(SILValue callee) const {
162-
return getCalleeListForCalleeKind(callee);
163-
}
164-
165-
/// Return the list of callees that can potentially be called at the
166-
/// given instruction. E.g. it could be destructors.
167-
CalleeList getDestructors(SILType type, bool isExactType) const;
168-
169-
CalleeList getCalleeList(SILDeclRef Decl) const;
170-
171-
private:
172-
void enumerateFunctionsInModule();
173-
void sortAndUniqueCallees();
174-
CalleesAndCanCallUnknown &getOrCreateCalleesForMethod(SILDeclRef Decl);
175-
void computeClassMethodCallees();
176-
void computeWitnessMethodCalleesForWitnessTable(SILWitnessTable &WT);
177-
void computeMethodCallees();
178-
SILFunction *getSingleCalleeForWitnessMethod(WitnessMethodInst *WMI) const;
179-
CalleeList getCalleeList(WitnessMethodInst *WMI) const;
180-
CalleeList getCalleeList(ClassMethodInst *CMI) const;
181-
CalleeList getCalleeListForCalleeKind(SILValue Callee) const;
182-
};
183-
18431
class BasicCalleeAnalysis : public SILAnalysis {
18532
SILModule &M;
18633
std::unique_ptr<CalleeCache> Cache;

include/swift/SILOptimizer/Utils/InstOptUtils.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -423,14 +423,6 @@ bool canReplaceLoadSequence(SILInstruction *inst);
423423
/// starting with the innermost struct_element_addr
424424
void replaceLoadSequence(SILInstruction *inst, SILValue value);
425425

426-
/// Do we have enough information to determine all callees that could
427-
/// be reached by calling the function represented by Decl?
428-
bool calleesAreStaticallyKnowable(SILModule &module, SILDeclRef decl);
429-
430-
/// Do we have enough information to determine all callees that could
431-
/// be reached by calling the function represented by Decl?
432-
bool calleesAreStaticallyKnowable(SILModule &module, ValueDecl *vd);
433-
434426
// Attempt to get the instance for , whose static type is the same as
435427
// its exact dynamic type, returning a null SILValue() if we cannot find it.
436428
// The information that a static type is the same as the exact dynamic,

lib/SIL/Utils/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
target_sources(swiftSIL PRIVATE
22
BasicBlockUtils.cpp
33
BitDataflow.cpp
4+
CalleeCache.cpp
45
DebugUtils.cpp
56
Dominance.cpp
67
DynamicCasts.cpp

0 commit comments

Comments
 (0)