Skip to content

Commit 0acc0a8

Browse files
committed
Implement a Caller Analysis.
The analysis can tell all the callsites which calls a function in the module. The analysis is computed and kept up-to-date lazily. At the core of it, it keeps a list of functions that need to be recomputed for the Caller/Callee relation to be precise and on every query, the analysis makes sure to recompute them and clear the list before any query. This is NFC right now. I am going to wire it up to function signature analysis eventually.
1 parent c43943d commit 0acc0a8

File tree

6 files changed

+176
-0
lines changed

6 files changed

+176
-0
lines changed

include/swift/SILOptimizer/Analysis/Analysis.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
ANALYSIS(Alias)
2727
ANALYSIS(BasicCallee)
28+
ANALYSIS(Caller)
2829
ANALYSIS(ClassHierarchy)
2930
ANALYSIS(Destructor)
3031
ANALYSIS(Dominance)

include/swift/SILOptimizer/Analysis/Analysis.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ namespace swift {
117117
/// Invalidate all of the information for a specific function.
118118
virtual void invalidate(SILFunction *F, InvalidationKind K) {}
119119

120+
virtual void notifyAnalysisOfFunction(SILFunction *F) {}
121+
120122
/// Verify the state of this analysis.
121123
virtual void verify() const {}
122124

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//===- CallerAnalysis.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 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_SILOPTIMIZER_ANALYSIS_CALLERANALYSIS_H
14+
#define SWIFT_SILOPTIMIZER_ANALYSIS_CALLERANALYSIS_H
15+
16+
#include "swift/SILOptimizer/Analysis/Analysis.h"
17+
#include "swift/SIL/SILFunction.h"
18+
#include "swift/SIL/SILInstruction.h"
19+
#include "swift/SIL/SILModule.h"
20+
#include "llvm/ADT/ArrayRef.h"
21+
#include "llvm/ADT/DenseMap.h"
22+
#include "llvm/ADT/SmallVector.h"
23+
#include "llvm/ADT/TinyPtrVector.h"
24+
25+
namespace swift {
26+
27+
using ApplyList = llvm::SmallVector<FullApplySite, 4>;
28+
29+
struct CallerAnalysisFunctionInfo {
30+
/// A list of all the functions this function calls.
31+
llvm::SmallVector<SILFunction *, 4> Callees;
32+
/// A map between all the callers and the callsites in them which
33+
/// calls this function.
34+
llvm::DenseMap<SILFunction *, ApplyList> CallSites;
35+
};
36+
37+
class CallerAnalysis : public SILAnalysis {
38+
/// Current module we are analyzing.
39+
SILModule &Mod;
40+
41+
/// A map between all the functions and their callsites in the module.
42+
llvm::DenseMap<SILFunction *, CallerAnalysisFunctionInfo> CallInfo;
43+
44+
/// A list of functions that needs to be recomputed.
45+
llvm::DenseSet<SILFunction *> RecomputeFunctionList;
46+
47+
/// Iterate over all the call sites in the function and update
48+
/// FuncToCallsites.
49+
void processFunctionCallSites(SILFunction *F);
50+
51+
/// This function is about to become "unknown" to us. Invalidate any
52+
/// callsite information related to it.
53+
void invalidateExistingCalleeRelation(SILFunction *F);
54+
55+
public:
56+
CallerAnalysis(SILModule *M) : SILAnalysis(AnalysisKind::Caller), Mod(*M) {
57+
// Make sure we compute everything first time called.
58+
for(auto &F : Mod) {
59+
RecomputeFunctionList.insert(&F);
60+
}
61+
}
62+
63+
static bool classof(const SILAnalysis *S) {
64+
return S->getKind() == AnalysisKind::Caller;
65+
}
66+
67+
virtual void notifyAnalysisOfFunction(SILFunction *F) {
68+
RecomputeFunctionList.insert(F);
69+
}
70+
71+
virtual void invalidate(SILFunction *F, InvalidationKind K) {
72+
// This function has become "unknown" to us. Invalidate any callsite
73+
// information related to this function.
74+
invalidateExistingCalleeRelation(F);
75+
// Make sure this function is recomputed next time.
76+
RecomputeFunctionList.insert(F);
77+
}
78+
79+
/// Return true if the function has a caller inside current module.
80+
bool existCaller(SILFunction *F) {
81+
// Recompute every function in the invaldiated function list and empty the
82+
// list.
83+
for (auto &F : RecomputeFunctionList) {
84+
processFunctionCallSites(F);
85+
}
86+
RecomputeFunctionList.clear();
87+
88+
auto Iter = CallInfo.FindAndConstruct(F);
89+
return !Iter.second.CallSites.empty();
90+
}
91+
92+
};
93+
94+
} // end namespace swift
95+
96+
#endif

include/swift/SILOptimizer/PassManager/PassManager.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ class SILPassManager {
125125
CompletedPassesMap.clear();
126126
}
127127

128+
void notifyAnalysisOfFunction(SILFunction *F) {
129+
for (auto AP : Analysis)
130+
AP->notifyAnalysisOfFunction(F);
131+
}
132+
128133
/// \brief Broadcast the invalidation of the function to all analysis.
129134
void invalidateAnalysis(SILFunction *F,
130135
SILAnalysis::InvalidationKind K) {

lib/SILOptimizer/Analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ set(ANALYSIS_SOURCES
44
Analysis/Analysis.cpp
55
Analysis/ArraySemantic.cpp
66
Analysis/BasicCalleeAnalysis.cpp
7+
Analysis/CallerAnalysis.cpp
78
Analysis/CFG.cpp
89
Analysis/ClassHierarchyAnalysis.cpp
910
Analysis/ColdBlockInfo.cpp
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//===--- CallerAnalysis.cpp - Determine callsites to a function ----------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "swift/SILOptimizer/Analysis/CallerAnalysis.h"
14+
15+
#include "swift/Basic/Fallthrough.h"
16+
#include "swift/SIL/SILModule.h"
17+
#include "swift/SILOptimizer/Utils/Local.h"
18+
19+
using namespace swift;
20+
21+
static SILFunction *getCallee(FullApplySite &Apply) {
22+
SILValue Callee = Apply.getCallee();
23+
// Strip ThinToThickFunctionInst.
24+
if (auto TTTF = dyn_cast<ThinToThickFunctionInst>(Callee)) {
25+
Callee = TTTF->getOperand();
26+
}
27+
28+
// Find the target function.
29+
auto *FRI = dyn_cast<FunctionRefInst>(Callee);
30+
if (!FRI)
31+
return nullptr;
32+
33+
return FRI->getReferencedFunction();
34+
}
35+
36+
void CallerAnalysis::processFunctionCallSites(SILFunction *F) {
37+
// Scan the whole module and search Apply sites.
38+
for (auto &BB : *F) {
39+
for (auto &II : BB) {
40+
if (auto Apply = FullApplySite::isa(&II)) {
41+
SILFunction *CalleeFn = getCallee(Apply);
42+
if (!CalleeFn)
43+
continue;
44+
// Update the callee information for this fucntion.
45+
CallerAnalysisFunctionInfo &CallerInfo
46+
= CallInfo.FindAndConstruct(F).second;
47+
CallerInfo.Callees.push_back(CalleeFn);
48+
49+
// Update the callsite information for the callee.
50+
CallerAnalysisFunctionInfo &CalleeInfo
51+
= CallInfo.FindAndConstruct(CalleeFn).second;
52+
CalleeInfo.CallSites[F].push_back(Apply);
53+
}
54+
}
55+
}
56+
}
57+
58+
void CallerAnalysis::invalidateExistingCalleeRelation(SILFunction *F) {
59+
CallerAnalysisFunctionInfo &CallerInfo = CallInfo.FindAndConstruct(F).second;
60+
for (auto Callee : CallerInfo.Callees) {
61+
CallerAnalysisFunctionInfo &CalleeInfo = CallInfo.find(Callee)->second;
62+
CalleeInfo.CallSites[F].clear();
63+
}
64+
}
65+
66+
//===----------------------------------------------------------------------===//
67+
// Main Entry Point
68+
//===----------------------------------------------------------------------===//
69+
SILAnalysis *swift::createCallerAnalysis(SILModule *M) {
70+
return new CallerAnalysis(M);
71+
}

0 commit comments

Comments
 (0)