LLVM 20.0.0git
SampleProfileInference.h
Go to the documentation of this file.
1//===- Transforms/Utils/SampleProfileInference.h ----------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// This file provides the interface for the profile inference algorithm, profi.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_TRANSFORMS_UTILS_SAMPLEPROFILEINFERENCE_H
15#define LLVM_TRANSFORMS_UTILS_SAMPLEPROFILEINFERENCE_H
16
17#include "llvm/ADT/DenseMap.h"
20
21namespace llvm {
22
23struct FlowJump;
24
25/// A wrapper of a binary basic block.
26struct FlowBlock {
29 bool HasUnknownWeight{true};
30 bool IsUnlikely{false};
32 std::vector<FlowJump *> SuccJumps;
33 std::vector<FlowJump *> PredJumps;
34
35 /// Check if it is the entry block in the function.
36 bool isEntry() const { return PredJumps.empty(); }
37
38 /// Check if it is an exit block in the function.
39 bool isExit() const { return SuccJumps.empty(); }
40};
41
42/// A wrapper of a jump between two basic blocks.
43struct FlowJump {
47 bool HasUnknownWeight{true};
48 bool IsUnlikely{false};
50};
51
52/// A wrapper of binary function with basic blocks and jumps.
54 /// Basic blocks in the function.
55 std::vector<FlowBlock> Blocks;
56 /// Jumps between the basic blocks.
57 std::vector<FlowJump> Jumps;
58 /// The index of the entry block.
60};
61
62/// Various thresholds and options controlling the behavior of the profile
63/// inference algorithm. Default values are tuned for several large-scale
64/// applications, and can be modified via corresponding command-line flags.
66 /// Evenly distribute flow when there are multiple equally likely options.
68
69 /// Evenly re-distribute flow among unknown subgraphs.
70 bool RebalanceUnknown{false};
71
72 /// Join isolated components having positive flow.
73 bool JoinIslands{false};
74
75 /// The cost of increasing a block's count by one.
76 unsigned CostBlockInc{0};
77
78 /// The cost of decreasing a block's count by one.
79 unsigned CostBlockDec{0};
80
81 /// The cost of increasing a count of zero-weight block by one.
82 unsigned CostBlockZeroInc{0};
83
84 /// The cost of increasing the entry block's count by one.
85 unsigned CostBlockEntryInc{0};
86
87 /// The cost of decreasing the entry block's count by one.
88 unsigned CostBlockEntryDec{0};
89
90 /// The cost of increasing an unknown block's count by one.
92
93 /// The cost of increasing a jump's count by one.
94 unsigned CostJumpInc{0};
95
96 /// The cost of increasing a fall-through jump's count by one.
97 unsigned CostJumpFTInc{0};
98
99 /// The cost of decreasing a jump's count by one.
100 unsigned CostJumpDec{0};
101
102 /// The cost of decreasing a fall-through jump's count by one.
103 unsigned CostJumpFTDec{0};
104
105 /// The cost of increasing an unknown jump's count by one.
107
108 /// The cost of increasing an unknown fall-through jump's count by one.
110
111 /// The cost of taking an unlikely block/jump.
112 const int64_t CostUnlikely = ((int64_t)1) << 30;
113};
114
115void applyFlowInference(const ProfiParams &Params, FlowFunction &Func);
117
118/// Sample profile inference pass.
119template <typename FT> class SampleProfileInference {
120public:
122 using BasicBlockT = std::remove_pointer_t<NodeRef>;
123 using FunctionT = FT;
124 using Edge = std::pair<const BasicBlockT *, const BasicBlockT *>;
129
131 BlockWeightMap &SampleBlockWeights)
132 : F(F), Successors(Successors), SampleBlockWeights(SampleBlockWeights) {}
133
134 /// Apply the profile inference algorithm for a given function
135 void apply(BlockWeightMap &BlockWeights, EdgeWeightMap &EdgeWeights);
136
137private:
138 /// Initialize flow function blocks, jumps and misc metadata.
140 createFlowFunction(const std::vector<const BasicBlockT *> &BasicBlocks,
142
143 /// Try to infer branch probabilities mimicking implementation of
144 /// BranchProbabilityInfo. Unlikely taken branches are marked so that the
145 /// inference algorithm can avoid sending flow along corresponding edges.
146 void findUnlikelyJumps(const std::vector<const BasicBlockT *> &BasicBlocks,
147 BlockEdgeMap &Successors, FlowFunction &Func);
148
149 /// Determine whether the block is an exit in the CFG.
150 bool isExit(const BasicBlockT *BB);
151
152 /// Function.
153 const FunctionT &F;
154
155 /// Successors for each basic block in the CFG.
156 BlockEdgeMap &Successors;
157
158 /// Map basic blocks to their sampled weights.
159 BlockWeightMap &SampleBlockWeights;
160};
161
162template <typename BT>
164 EdgeWeightMap &EdgeWeights) {
165 // Find all forwards reachable blocks which the inference algorithm will be
166 // applied on.
168 for (auto *BB : depth_first_ext(&F, Reachable))
169 (void)BB /* Mark all reachable blocks */;
170
171 // Find all backwards reachable blocks which the inference algorithm will be
172 // applied on.
174 for (const auto &BB : F) {
175 // An exit block is a block without any successors.
176 if (isExit(&BB)) {
177 for (auto *RBB : inverse_depth_first_ext(&BB, InverseReachable))
178 (void)RBB;
179 }
180 }
181
182 // Keep a stable order for reachable blocks
184 std::vector<const BasicBlockT *> BasicBlocks;
185 BlockIndex.reserve(Reachable.size());
186 BasicBlocks.reserve(Reachable.size());
187 for (const auto &BB : F) {
188 if (Reachable.count(&BB) && InverseReachable.count(&BB)) {
189 BlockIndex[&BB] = BasicBlocks.size();
190 BasicBlocks.push_back(&BB);
191 }
192 }
193
194 BlockWeights.clear();
195 EdgeWeights.clear();
196 bool HasSamples = false;
197 for (const auto *BB : BasicBlocks) {
198 auto It = SampleBlockWeights.find(BB);
199 if (It != SampleBlockWeights.end() && It->second > 0) {
200 HasSamples = true;
201 BlockWeights[BB] = It->second;
202 }
203 }
204 // Quit early for functions with a single block or ones w/o samples
205 if (BasicBlocks.size() <= 1 || !HasSamples) {
206 return;
207 }
208
209 // Create necessary objects
210 FlowFunction Func = createFlowFunction(BasicBlocks, BlockIndex);
211
212 // Create and apply the inference network model.
213 applyFlowInference(Func);
214
215 // Extract the resulting weights from the control flow
216 // All weights are increased by one to avoid propagation errors introduced by
217 // zero weights.
218 for (const auto *BB : BasicBlocks) {
219 BlockWeights[BB] = Func.Blocks[BlockIndex[BB]].Flow;
220 }
221 for (auto &Jump : Func.Jumps) {
222 Edge E = std::make_pair(BasicBlocks[Jump.Source], BasicBlocks[Jump.Target]);
223 EdgeWeights[E] = Jump.Flow;
224 }
225
226#ifndef NDEBUG
227 // Unreachable blocks and edges should not have a weight.
228 for (auto &I : BlockWeights) {
229 assert(Reachable.contains(I.first));
230 assert(InverseReachable.contains(I.first));
231 }
232 for (auto &I : EdgeWeights) {
233 assert(Reachable.contains(I.first.first) &&
234 Reachable.contains(I.first.second));
235 assert(InverseReachable.contains(I.first.first) &&
236 InverseReachable.contains(I.first.second));
237 }
238#endif
239}
240
241template <typename BT>
243 const std::vector<const BasicBlockT *> &BasicBlocks,
245 FlowFunction Func;
246 Func.Blocks.reserve(BasicBlocks.size());
247 // Create FlowBlocks
248 for (const auto *BB : BasicBlocks) {
250 auto It = SampleBlockWeights.find(BB);
251 if (It != SampleBlockWeights.end()) {
252 Block.HasUnknownWeight = false;
253 Block.Weight = It->second;
254 } else {
255 Block.HasUnknownWeight = true;
256 Block.Weight = 0;
257 }
258 Block.Index = Func.Blocks.size();
259 Func.Blocks.push_back(Block);
260 }
261 // Create FlowEdges
262 for (const auto *BB : BasicBlocks) {
263 for (auto *Succ : Successors[BB]) {
264 if (!BlockIndex.count(Succ))
265 continue;
266 FlowJump Jump;
267 Jump.Source = BlockIndex[BB];
268 Jump.Target = BlockIndex[Succ];
269 Func.Jumps.push_back(Jump);
270 }
271 }
272 for (auto &Jump : Func.Jumps) {
273 uint64_t Src = Jump.Source;
274 uint64_t Dst = Jump.Target;
275 Func.Blocks[Src].SuccJumps.push_back(&Jump);
276 Func.Blocks[Dst].PredJumps.push_back(&Jump);
277 }
278
279 // Try to infer probabilities of jumps based on the content of basic block
280 findUnlikelyJumps(BasicBlocks, Successors, Func);
281
282 // Find the entry block
283 for (size_t I = 0; I < Func.Blocks.size(); I++) {
284 if (Func.Blocks[I].isEntry()) {
285 Func.Entry = I;
286 break;
287 }
288 }
289 assert(Func.Entry == 0 && "incorrect index of the entry block");
290
291 // Pre-process data: make sure the entry weight is at least 1
292 auto &EntryBlock = Func.Blocks[Func.Entry];
293 if (EntryBlock.Weight == 0 && !EntryBlock.HasUnknownWeight) {
294 EntryBlock.Weight = 1;
295 EntryBlock.HasUnknownWeight = false;
296 }
297
298 return Func;
299}
300
301template <typename BT>
302inline void SampleProfileInference<BT>::findUnlikelyJumps(
303 const std::vector<const BasicBlockT *> &BasicBlocks,
304 BlockEdgeMap &Successors, FlowFunction &Func) {}
305
306template <typename BT>
307inline bool SampleProfileInference<BT>::isExit(const BasicBlockT *BB) {
308 return BB->succ_empty();
309}
310
311} // end namespace llvm
312#endif // LLVM_TRANSFORMS_UTILS_SAMPLEPROFILEINFERENCE_H
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
unsigned size() const
Definition: DenseMap.h:99
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:152
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Definition: DenseMap.h:103
Sample profile inference pass.
std::remove_pointer_t< NodeRef > BasicBlockT
DenseMap< const BasicBlockT *, uint64_t > BlockWeightMap
typename GraphTraits< FT * >::NodeRef NodeRef
DenseMap< const BasicBlockT *, SmallVector< const BasicBlockT *, 8 > > BlockEdgeMap
DenseMap< Edge, uint64_t > EdgeWeightMap
std::pair< const BasicBlockT *, const BasicBlockT * > Edge
void apply(BlockWeightMap &BlockWeights, EdgeWeightMap &EdgeWeights)
Apply the profile inference algorithm for a given function.
SampleProfileInference(FunctionT &F, BlockEdgeMap &Successors, BlockWeightMap &SampleBlockWeights)
size_type size() const
Definition: SmallPtrSet.h:94
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
Definition: SmallPtrSet.h:452
bool contains(ConstPtrType Ptr) const
Definition: SmallPtrSet.h:458
NodeAddr< FuncNode * > Func
Definition: RDFGraph.h:393
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
iterator_range< df_ext_iterator< T, SetTy > > depth_first_ext(const T &G, SetTy &S)
iterator_range< idf_ext_iterator< T, SetTy > > inverse_depth_first_ext(const T &G, SetTy &S)
void applyFlowInference(const ProfiParams &Params, FlowFunction &Func)
Apply the profile inference algorithm for a given function and provided profi options.
A wrapper of a binary basic block.
bool isEntry() const
Check if it is the entry block in the function.
bool isExit() const
Check if it is an exit block in the function.
std::vector< FlowJump * > PredJumps
std::vector< FlowJump * > SuccJumps
A wrapper of binary function with basic blocks and jumps.
std::vector< FlowJump > Jumps
Jumps between the basic blocks.
std::vector< FlowBlock > Blocks
Basic blocks in the function.
uint64_t Entry
The index of the entry block.
A wrapper of a jump between two basic blocks.
typename GraphType::UnknownGraphTypeError NodeRef
Definition: GraphTraits.h:95
Various thresholds and options controlling the behavior of the profile inference algorithm.
unsigned CostJumpUnknownFTInc
The cost of increasing an unknown fall-through jump's count by one.
unsigned CostBlockInc
The cost of increasing a block's count by one.
unsigned CostJumpFTInc
The cost of increasing a fall-through jump's count by one.
bool RebalanceUnknown
Evenly re-distribute flow among unknown subgraphs.
const int64_t CostUnlikely
The cost of taking an unlikely block/jump.
unsigned CostJumpDec
The cost of decreasing a jump's count by one.
bool JoinIslands
Join isolated components having positive flow.
unsigned CostBlockZeroInc
The cost of increasing a count of zero-weight block by one.
unsigned CostBlockEntryDec
The cost of decreasing the entry block's count by one.
unsigned CostJumpInc
The cost of increasing a jump's count by one.
unsigned CostJumpUnknownInc
The cost of increasing an unknown jump's count by one.
unsigned CostBlockUnknownInc
The cost of increasing an unknown block's count by one.
unsigned CostJumpFTDec
The cost of decreasing a fall-through jump's count by one.
unsigned CostBlockDec
The cost of decreasing a block's count by one.
unsigned CostBlockEntryInc
The cost of increasing the entry block's count by one.
bool EvenFlowDistribution
Evenly distribute flow when there are multiple equally likely options.