12
12
// ===----------------------------------------------------------------------===//
13
13
14
14
#include " llvm/Analysis/FunctionPropertiesAnalysis.h"
15
+ #include " llvm/ADT/STLExtras.h"
15
16
#include " llvm/Analysis/LoopInfo.h"
17
+ #include " llvm/IR/CFG.h"
16
18
#include " llvm/IR/Instructions.h"
19
+ #include < deque>
17
20
18
21
using namespace llvm ;
19
22
20
- FunctionPropertiesInfo
21
- FunctionPropertiesInfo::getFunctionPropertiesInfo (const Function &F,
22
- const LoopInfo &LI) {
23
-
24
- FunctionPropertiesInfo FPI;
23
+ namespace {
24
+ int64_t getNrBlocksFromCond (const BasicBlock &BB) {
25
+ int64_t Ret = 0 ;
26
+ if (const auto *BI = dyn_cast<BranchInst>(BB.getTerminator ())) {
27
+ if (BI->isConditional ())
28
+ Ret += BI->getNumSuccessors ();
29
+ } else if (const auto *SI = dyn_cast<SwitchInst>(BB.getTerminator ())) {
30
+ Ret += (SI->getNumCases () + (nullptr != SI->getDefaultDest ()));
31
+ }
32
+ return Ret;
33
+ }
25
34
26
- FPI.Uses = ((!F.hasLocalLinkage ()) ? 1 : 0 ) + F.getNumUses ();
35
+ int64_t getUses (const Function &F) {
36
+ return ((!F.hasLocalLinkage ()) ? 1 : 0 ) + F.getNumUses ();
37
+ }
38
+ } // namespace
27
39
28
- for (const auto &BB : F) {
29
- ++FPI.BasicBlockCount ;
40
+ void FunctionPropertiesInfo::reIncludeBB (const BasicBlock &BB,
41
+ const LoopInfo &LI) {
42
+ updateForBB (BB, +1 );
43
+ MaxLoopDepth =
44
+ std::max (MaxLoopDepth, static_cast <int64_t >(LI.getLoopDepth (&BB)));
45
+ }
30
46
31
- if (const auto *BI = dyn_cast<BranchInst>(BB.getTerminator ())) {
32
- if (BI->isConditional ())
33
- FPI.BlocksReachedFromConditionalInstruction += BI->getNumSuccessors ();
34
- } else if (const auto *SI = dyn_cast<SwitchInst>(BB.getTerminator ())) {
35
- FPI.BlocksReachedFromConditionalInstruction +=
36
- (SI->getNumCases () + (nullptr != SI->getDefaultDest ()));
47
+ void FunctionPropertiesInfo::updateForBB (const BasicBlock &BB,
48
+ int64_t Direction) {
49
+ assert (Direction == 1 || Direction == -1 );
50
+ BasicBlockCount += Direction;
51
+ BlocksReachedFromConditionalInstruction +=
52
+ (Direction * getNrBlocksFromCond (BB));
53
+ for (const auto &I : BB) {
54
+ if (auto *CS = dyn_cast<CallBase>(&I)) {
55
+ const auto *Callee = CS->getCalledFunction ();
56
+ if (Callee && !Callee->isIntrinsic () && !Callee->isDeclaration ())
57
+ DirectCallsToDefinedFunctions += Direction;
37
58
}
38
-
39
- for (const auto &I : BB) {
40
- if (auto *CS = dyn_cast<CallBase>(&I)) {
41
- const auto *Callee = CS->getCalledFunction ();
42
- if (Callee && !Callee->isIntrinsic () && !Callee->isDeclaration ())
43
- ++FPI.DirectCallsToDefinedFunctions ;
44
- }
45
- if (I.getOpcode () == Instruction::Load) {
46
- ++FPI.LoadInstCount ;
47
- } else if (I.getOpcode () == Instruction::Store) {
48
- ++FPI.StoreInstCount ;
49
- }
59
+ if (I.getOpcode () == Instruction::Load) {
60
+ LoadInstCount += Direction;
61
+ } else if (I.getOpcode () == Instruction::Store) {
62
+ StoreInstCount += Direction;
50
63
}
51
- // Loop Depth of the Basic Block
52
- int64_t LoopDepth;
53
- LoopDepth = LI.getLoopDepth (&BB);
54
- if (FPI.MaxLoopDepth < LoopDepth)
55
- FPI.MaxLoopDepth = LoopDepth;
56
64
}
57
- FPI.TopLevelLoopCount += llvm::size (LI);
65
+ TotalInstructionCount += Direction * BB.sizeWithoutDebug ();
66
+ }
67
+
68
+ void FunctionPropertiesInfo::updateAggregateStats (const Function &F,
69
+ const LoopInfo &LI) {
70
+
71
+ Uses = getUses (F);
72
+ TopLevelLoopCount = llvm::size (LI);
73
+ }
74
+
75
+ FunctionPropertiesInfo
76
+ FunctionPropertiesInfo::getFunctionPropertiesInfo (const Function &F,
77
+ const LoopInfo &LI) {
78
+
79
+ FunctionPropertiesInfo FPI;
80
+ for (const auto &BB : F)
81
+ if (!pred_empty (&BB) || BB.isEntryBlock ())
82
+ FPI.reIncludeBB (BB, LI);
83
+ FPI.updateAggregateStats (F, LI);
58
84
return FPI;
59
85
}
60
86
@@ -68,7 +94,8 @@ void FunctionPropertiesInfo::print(raw_ostream &OS) const {
68
94
<< " LoadInstCount: " << LoadInstCount << " \n "
69
95
<< " StoreInstCount: " << StoreInstCount << " \n "
70
96
<< " MaxLoopDepth: " << MaxLoopDepth << " \n "
71
- << " TopLevelLoopCount: " << TopLevelLoopCount << " \n\n " ;
97
+ << " TopLevelLoopCount: " << TopLevelLoopCount << " \n "
98
+ << " TotalInstructionCount: " << TotalInstructionCount << " \n\n " ;
72
99
}
73
100
74
101
AnalysisKey FunctionPropertiesAnalysis::Key;
@@ -87,3 +114,60 @@ FunctionPropertiesPrinterPass::run(Function &F, FunctionAnalysisManager &AM) {
87
114
AM.getResult <FunctionPropertiesAnalysis>(F).print (OS);
88
115
return PreservedAnalyses::all ();
89
116
}
117
+
118
+ FunctionPropertiesUpdater::FunctionPropertiesUpdater (
119
+ FunctionPropertiesInfo &FPI, const CallBase &CB)
120
+ : FPI(FPI), CallSiteBB(*CB.getParent()), Caller(*CallSiteBB.getParent()) {
121
+
122
+ // For BBs that are likely to change, we subtract from feature totals their
123
+ // contribution. Some features, like max loop counts or depths, are left
124
+ // invalid, as they will be updated post-inlining.
125
+ SmallPtrSet<const BasicBlock *, 4 > LikelyToChangeBBs;
126
+ // The CB BB will change - it'll either be split or the callee's body (single
127
+ // BB) will be pasted in.
128
+ LikelyToChangeBBs.insert (&CallSiteBB);
129
+
130
+ // The caller's entry BB may change due to new alloca instructions.
131
+ LikelyToChangeBBs.insert (&*Caller.begin ());
132
+
133
+ // The successors may become unreachable in the case of `invoke` inlining.
134
+ // We track successors separately, too, because they form a boundary, together
135
+ // with the CB BB ('Entry') between which the inlined callee will be pasted.
136
+ Successors.insert (succ_begin (&CallSiteBB), succ_end (&CallSiteBB));
137
+ for (const auto *BB : Successors)
138
+ LikelyToChangeBBs.insert (BB);
139
+
140
+ // Commit the change. While some of the BBs accounted for above may play dual
141
+ // role - e.g. caller's entry BB may be the same as the callsite BB - set
142
+ // insertion semantics make sure we account them once. This needs to be
143
+ // followed in `finish`, too.
144
+ for (const auto *BB : LikelyToChangeBBs)
145
+ FPI.updateForBB (*BB, -1 );
146
+ }
147
+
148
+ void FunctionPropertiesUpdater::finish (const LoopInfo &LI) {
149
+ DenseSet<const BasicBlock *> ReIncluded;
150
+ std::deque<const BasicBlock *> Worklist;
151
+
152
+ if (&CallSiteBB != &*Caller.begin ()) {
153
+ FPI.reIncludeBB (*Caller.begin (), LI);
154
+ ReIncluded.insert (&*Caller.begin ());
155
+ }
156
+
157
+ // Update feature values from the BBs that were copied from the callee, or
158
+ // might have been modified because of inlining. The latter have been
159
+ // subtracted in the FunctionPropertiesUpdater ctor.
160
+ Worklist.push_back (&CallSiteBB);
161
+ while (!Worklist.empty ()) {
162
+ const auto *BB = Worklist.front ();
163
+ Worklist.pop_front ();
164
+ if (!ReIncluded.insert (BB).second )
165
+ continue ;
166
+ FPI.reIncludeBB (*BB, LI);
167
+ if (!Successors.contains (BB))
168
+ for (const auto *Succ : successors (BB))
169
+ Worklist.push_back (Succ);
170
+ }
171
+ FPI.updateAggregateStats (Caller, LI);
172
+ assert (FPI == FunctionPropertiesInfo::getFunctionPropertiesInfo (Caller, LI));
173
+ }
0 commit comments