Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- BranchProbabilityInfo.h - Branch Probability Analysis ----*- 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 | // This pass is used to evaluate branch probabilties. |
||
10 | // |
||
11 | //===----------------------------------------------------------------------===// |
||
12 | |||
13 | #ifndef LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H |
||
14 | #define LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H |
||
15 | |||
16 | #include "llvm/ADT/DenseMap.h" |
||
17 | #include "llvm/ADT/DenseMapInfo.h" |
||
18 | #include "llvm/ADT/DenseSet.h" |
||
19 | #include "llvm/IR/BasicBlock.h" |
||
20 | #include "llvm/IR/CFG.h" |
||
21 | #include "llvm/IR/PassManager.h" |
||
22 | #include "llvm/IR/ValueHandle.h" |
||
23 | #include "llvm/Pass.h" |
||
24 | #include "llvm/Support/BranchProbability.h" |
||
25 | #include <algorithm> |
||
26 | #include <cassert> |
||
27 | #include <cstdint> |
||
28 | #include <memory> |
||
29 | #include <utility> |
||
30 | |||
31 | namespace llvm { |
||
32 | |||
33 | class Function; |
||
34 | class Loop; |
||
35 | class LoopInfo; |
||
36 | class raw_ostream; |
||
37 | class DominatorTree; |
||
38 | class PostDominatorTree; |
||
39 | class TargetLibraryInfo; |
||
40 | class Value; |
||
41 | |||
42 | /// Analysis providing branch probability information. |
||
43 | /// |
||
44 | /// This is a function analysis which provides information on the relative |
||
45 | /// probabilities of each "edge" in the function's CFG where such an edge is |
||
46 | /// defined by a pair (PredBlock and an index in the successors). The |
||
47 | /// probability of an edge from one block is always relative to the |
||
48 | /// probabilities of other edges from the block. The probabilites of all edges |
||
49 | /// from a block sum to exactly one (100%). |
||
50 | /// We use a pair (PredBlock and an index in the successors) to uniquely |
||
51 | /// identify an edge, since we can have multiple edges from Src to Dst. |
||
52 | /// As an example, we can have a switch which jumps to Dst with value 0 and |
||
53 | /// value 10. |
||
54 | /// |
||
55 | /// Process of computing branch probabilities can be logically viewed as three |
||
56 | /// step process: |
||
57 | /// |
||
58 | /// First, if there is a profile information associated with the branch then |
||
59 | /// it is trivially translated to branch probabilities. There is one exception |
||
60 | /// from this rule though. Probabilities for edges leading to "unreachable" |
||
61 | /// blocks (blocks with the estimated weight not greater than |
||
62 | /// UNREACHABLE_WEIGHT) are evaluated according to static estimation and |
||
63 | /// override profile information. If no branch probabilities were calculated |
||
64 | /// on this step then take the next one. |
||
65 | /// |
||
66 | /// Second, estimate absolute execution weights for each block based on |
||
67 | /// statically known information. Roots of such information are "cold", |
||
68 | /// "unreachable", "noreturn" and "unwind" blocks. Those blocks get their |
||
69 | /// weights set to BlockExecWeight::COLD, BlockExecWeight::UNREACHABLE, |
||
70 | /// BlockExecWeight::NORETURN and BlockExecWeight::UNWIND respectively. Then the |
||
71 | /// weights are propagated to the other blocks up the domination line. In |
||
72 | /// addition, if all successors have estimated weights set then maximum of these |
||
73 | /// weights assigned to the block itself (while this is not ideal heuristic in |
||
74 | /// theory it's simple and works reasonably well in most cases) and the process |
||
75 | /// repeats. Once the process of weights propagation converges branch |
||
76 | /// probabilities are set for all such branches that have at least one successor |
||
77 | /// with the weight set. Default execution weight (BlockExecWeight::DEFAULT) is |
||
78 | /// used for any successors which doesn't have its weight set. For loop back |
||
79 | /// branches we use their weights scaled by loop trip count equal to |
||
80 | /// 'LBH_TAKEN_WEIGHT/LBH_NOTTAKEN_WEIGHT'. |
||
81 | /// |
||
82 | /// Here is a simple example demonstrating how the described algorithm works. |
||
83 | /// |
||
84 | /// BB1 |
||
85 | /// / \ |
||
86 | /// v v |
||
87 | /// BB2 BB3 |
||
88 | /// / \ |
||
89 | /// v v |
||
90 | /// ColdBB UnreachBB |
||
91 | /// |
||
92 | /// Initially, ColdBB is associated with COLD_WEIGHT and UnreachBB with |
||
93 | /// UNREACHABLE_WEIGHT. COLD_WEIGHT is set to BB2 as maximum between its |
||
94 | /// successors. BB1 and BB3 has no explicit estimated weights and assumed to |
||
95 | /// have DEFAULT_WEIGHT. Based on assigned weights branches will have the |
||
96 | /// following probabilities: |
||
97 | /// P(BB1->BB2) = COLD_WEIGHT/(COLD_WEIGHT + DEFAULT_WEIGHT) = |
||
98 | /// 0xffff / (0xffff + 0xfffff) = 0.0588(5.9%) |
||
99 | /// P(BB1->BB3) = DEFAULT_WEIGHT_WEIGHT/(COLD_WEIGHT + DEFAULT_WEIGHT) = |
||
100 | /// 0xfffff / (0xffff + 0xfffff) = 0.941(94.1%) |
||
101 | /// P(BB2->ColdBB) = COLD_WEIGHT/(COLD_WEIGHT + UNREACHABLE_WEIGHT) = 1(100%) |
||
102 | /// P(BB2->UnreachBB) = |
||
103 | /// UNREACHABLE_WEIGHT/(COLD_WEIGHT+UNREACHABLE_WEIGHT) = 0(0%) |
||
104 | /// |
||
105 | /// If no branch probabilities were calculated on this step then take the next |
||
106 | /// one. |
||
107 | /// |
||
108 | /// Third, apply different kinds of local heuristics for each individual |
||
109 | /// branch until first match. For example probability of a pointer to be null is |
||
110 | /// estimated as PH_TAKEN_WEIGHT/(PH_TAKEN_WEIGHT + PH_NONTAKEN_WEIGHT). If |
||
111 | /// no local heuristic has been matched then branch is left with no explicit |
||
112 | /// probability set and assumed to have default probability. |
||
113 | class BranchProbabilityInfo { |
||
114 | public: |
||
115 | BranchProbabilityInfo() = default; |
||
116 | |||
117 | BranchProbabilityInfo(const Function &F, const LoopInfo &LI, |
||
118 | const TargetLibraryInfo *TLI = nullptr, |
||
119 | DominatorTree *DT = nullptr, |
||
120 | PostDominatorTree *PDT = nullptr) { |
||
121 | calculate(F, LI, TLI, DT, PDT); |
||
122 | } |
||
123 | |||
124 | BranchProbabilityInfo(BranchProbabilityInfo &&Arg) |
||
125 | : Probs(std::move(Arg.Probs)), LastF(Arg.LastF), |
||
126 | EstimatedBlockWeight(std::move(Arg.EstimatedBlockWeight)) {} |
||
127 | |||
128 | BranchProbabilityInfo(const BranchProbabilityInfo &) = delete; |
||
129 | BranchProbabilityInfo &operator=(const BranchProbabilityInfo &) = delete; |
||
130 | |||
131 | BranchProbabilityInfo &operator=(BranchProbabilityInfo &&RHS) { |
||
132 | releaseMemory(); |
||
133 | Probs = std::move(RHS.Probs); |
||
134 | EstimatedBlockWeight = std::move(RHS.EstimatedBlockWeight); |
||
135 | return *this; |
||
136 | } |
||
137 | |||
138 | bool invalidate(Function &, const PreservedAnalyses &PA, |
||
139 | FunctionAnalysisManager::Invalidator &); |
||
140 | |||
141 | void releaseMemory(); |
||
142 | |||
143 | void print(raw_ostream &OS) const; |
||
144 | |||
145 | /// Get an edge's probability, relative to other out-edges of the Src. |
||
146 | /// |
||
147 | /// This routine provides access to the fractional probability between zero |
||
148 | /// (0%) and one (100%) of this edge executing, relative to other edges |
||
149 | /// leaving the 'Src' block. The returned probability is never zero, and can |
||
150 | /// only be one if the source block has only one successor. |
||
151 | BranchProbability getEdgeProbability(const BasicBlock *Src, |
||
152 | unsigned IndexInSuccessors) const; |
||
153 | |||
154 | /// Get the probability of going from Src to Dst. |
||
155 | /// |
||
156 | /// It returns the sum of all probabilities for edges from Src to Dst. |
||
157 | BranchProbability getEdgeProbability(const BasicBlock *Src, |
||
158 | const BasicBlock *Dst) const; |
||
159 | |||
160 | BranchProbability getEdgeProbability(const BasicBlock *Src, |
||
161 | const_succ_iterator Dst) const; |
||
162 | |||
163 | /// Test if an edge is hot relative to other out-edges of the Src. |
||
164 | /// |
||
165 | /// Check whether this edge out of the source block is 'hot'. We define hot |
||
166 | /// as having a relative probability >= 80%. |
||
167 | bool isEdgeHot(const BasicBlock *Src, const BasicBlock *Dst) const; |
||
168 | |||
169 | /// Print an edge's probability. |
||
170 | /// |
||
171 | /// Retrieves an edge's probability similarly to \see getEdgeProbability, but |
||
172 | /// then prints that probability to the provided stream. That stream is then |
||
173 | /// returned. |
||
174 | raw_ostream &printEdgeProbability(raw_ostream &OS, const BasicBlock *Src, |
||
175 | const BasicBlock *Dst) const; |
||
176 | |||
177 | public: |
||
178 | /// Set the raw probabilities for all edges from the given block. |
||
179 | /// |
||
180 | /// This allows a pass to explicitly set edge probabilities for a block. It |
||
181 | /// can be used when updating the CFG to update the branch probability |
||
182 | /// information. |
||
183 | void setEdgeProbability(const BasicBlock *Src, |
||
184 | const SmallVectorImpl<BranchProbability> &Probs); |
||
185 | |||
186 | /// Copy outgoing edge probabilities from \p Src to \p Dst. |
||
187 | /// |
||
188 | /// This allows to keep probabilities unset for the destination if they were |
||
189 | /// unset for source. |
||
190 | void copyEdgeProbabilities(BasicBlock *Src, BasicBlock *Dst); |
||
191 | |||
192 | static BranchProbability getBranchProbStackProtector(bool IsLikely) { |
||
193 | static const BranchProbability LikelyProb((1u << 20) - 1, 1u << 20); |
||
194 | return IsLikely ? LikelyProb : LikelyProb.getCompl(); |
||
195 | } |
||
196 | |||
197 | void calculate(const Function &F, const LoopInfo &LI, |
||
198 | const TargetLibraryInfo *TLI, DominatorTree *DT, |
||
199 | PostDominatorTree *PDT); |
||
200 | |||
201 | /// Forget analysis results for the given basic block. |
||
202 | void eraseBlock(const BasicBlock *BB); |
||
203 | |||
204 | // Data structure to track SCCs for handling irreducible loops. |
||
205 | class SccInfo { |
||
206 | // Enum of types to classify basic blocks in SCC. Basic block belonging to |
||
207 | // SCC is 'Inner' until it is either 'Header' or 'Exiting'. Note that a |
||
208 | // basic block can be 'Header' and 'Exiting' at the same time. |
||
209 | enum SccBlockType { |
||
210 | Inner = 0x0, |
||
211 | Header = 0x1, |
||
212 | Exiting = 0x2, |
||
213 | }; |
||
214 | // Map of basic blocks to SCC IDs they belong to. If basic block doesn't |
||
215 | // belong to any SCC it is not in the map. |
||
216 | using SccMap = DenseMap<const BasicBlock *, int>; |
||
217 | // Each basic block in SCC is attributed with one or several types from |
||
218 | // SccBlockType. Map value has uint32_t type (instead of SccBlockType) |
||
219 | // since basic block may be for example "Header" and "Exiting" at the same |
||
220 | // time and we need to be able to keep more than one value from |
||
221 | // SccBlockType. |
||
222 | using SccBlockTypeMap = DenseMap<const BasicBlock *, uint32_t>; |
||
223 | // Vector containing classification of basic blocks for all SCCs where i'th |
||
224 | // vector element corresponds to SCC with ID equal to i. |
||
225 | using SccBlockTypeMaps = std::vector<SccBlockTypeMap>; |
||
226 | |||
227 | SccMap SccNums; |
||
228 | SccBlockTypeMaps SccBlocks; |
||
229 | |||
230 | public: |
||
231 | explicit SccInfo(const Function &F); |
||
232 | |||
233 | /// If \p BB belongs to some SCC then ID of that SCC is returned, otherwise |
||
234 | /// -1 is returned. If \p BB belongs to more than one SCC at the same time |
||
235 | /// result is undefined. |
||
236 | int getSCCNum(const BasicBlock *BB) const; |
||
237 | /// Returns true if \p BB is a 'header' block in SCC with \p SccNum ID, |
||
238 | /// false otherwise. |
||
239 | bool isSCCHeader(const BasicBlock *BB, int SccNum) const { |
||
240 | return getSccBlockType(BB, SccNum) & Header; |
||
241 | } |
||
242 | /// Returns true if \p BB is an 'exiting' block in SCC with \p SccNum ID, |
||
243 | /// false otherwise. |
||
244 | bool isSCCExitingBlock(const BasicBlock *BB, int SccNum) const { |
||
245 | return getSccBlockType(BB, SccNum) & Exiting; |
||
246 | } |
||
247 | /// Fills in \p Enters vector with all such blocks that don't belong to |
||
248 | /// SCC with \p SccNum ID but there is an edge to a block belonging to the |
||
249 | /// SCC. |
||
250 | void getSccEnterBlocks(int SccNum, |
||
251 | SmallVectorImpl<BasicBlock *> &Enters) const; |
||
252 | /// Fills in \p Exits vector with all such blocks that don't belong to |
||
253 | /// SCC with \p SccNum ID but there is an edge from a block belonging to the |
||
254 | /// SCC. |
||
255 | void getSccExitBlocks(int SccNum, |
||
256 | SmallVectorImpl<BasicBlock *> &Exits) const; |
||
257 | |||
258 | private: |
||
259 | /// Returns \p BB's type according to classification given by SccBlockType |
||
260 | /// enum. Please note that \p BB must belong to SSC with \p SccNum ID. |
||
261 | uint32_t getSccBlockType(const BasicBlock *BB, int SccNum) const; |
||
262 | /// Calculates \p BB's type and stores it in internal data structures for |
||
263 | /// future use. Please note that \p BB must belong to SSC with \p SccNum ID. |
||
264 | void calculateSccBlockType(const BasicBlock *BB, int SccNum); |
||
265 | }; |
||
266 | |||
267 | private: |
||
268 | // We need to store CallbackVH's in order to correctly handle basic block |
||
269 | // removal. |
||
270 | class BasicBlockCallbackVH final : public CallbackVH { |
||
271 | BranchProbabilityInfo *BPI; |
||
272 | |||
273 | void deleted() override { |
||
274 | assert(BPI != nullptr); |
||
275 | BPI->eraseBlock(cast<BasicBlock>(getValPtr())); |
||
276 | } |
||
277 | |||
278 | public: |
||
279 | BasicBlockCallbackVH(const Value *V, BranchProbabilityInfo *BPI = nullptr) |
||
280 | : CallbackVH(const_cast<Value *>(V)), BPI(BPI) {} |
||
281 | }; |
||
282 | |||
283 | /// Pair of Loop and SCC ID number. Used to unify handling of normal and |
||
284 | /// SCC based loop representations. |
||
285 | using LoopData = std::pair<Loop *, int>; |
||
286 | /// Helper class to keep basic block along with its loop data information. |
||
287 | class LoopBlock { |
||
288 | public: |
||
289 | explicit LoopBlock(const BasicBlock *BB, const LoopInfo &LI, |
||
290 | const SccInfo &SccI); |
||
291 | |||
292 | const BasicBlock *getBlock() const { return BB; } |
||
293 | BasicBlock *getBlock() { return const_cast<BasicBlock *>(BB); } |
||
294 | LoopData getLoopData() const { return LD; } |
||
295 | Loop *getLoop() const { return LD.first; } |
||
296 | int getSccNum() const { return LD.second; } |
||
297 | |||
298 | bool belongsToLoop() const { return getLoop() || getSccNum() != -1; } |
||
299 | bool belongsToSameLoop(const LoopBlock &LB) const { |
||
300 | return (LB.getLoop() && getLoop() == LB.getLoop()) || |
||
301 | (LB.getSccNum() != -1 && getSccNum() == LB.getSccNum()); |
||
302 | } |
||
303 | |||
304 | private: |
||
305 | const BasicBlock *const BB = nullptr; |
||
306 | LoopData LD = {nullptr, -1}; |
||
307 | }; |
||
308 | |||
309 | // Pair of LoopBlocks representing an edge from first to second block. |
||
310 | using LoopEdge = std::pair<const LoopBlock &, const LoopBlock &>; |
||
311 | |||
312 | DenseSet<BasicBlockCallbackVH, DenseMapInfo<Value*>> Handles; |
||
313 | |||
314 | // Since we allow duplicate edges from one basic block to another, we use |
||
315 | // a pair (PredBlock and an index in the successors) to specify an edge. |
||
316 | using Edge = std::pair<const BasicBlock *, unsigned>; |
||
317 | |||
318 | DenseMap<Edge, BranchProbability> Probs; |
||
319 | |||
320 | /// Track the last function we run over for printing. |
||
321 | const Function *LastF = nullptr; |
||
322 | |||
323 | const LoopInfo *LI = nullptr; |
||
324 | |||
325 | /// Keeps information about all SCCs in a function. |
||
326 | std::unique_ptr<const SccInfo> SccI; |
||
327 | |||
328 | /// Keeps mapping of a basic block to its estimated weight. |
||
329 | SmallDenseMap<const BasicBlock *, uint32_t> EstimatedBlockWeight; |
||
330 | |||
331 | /// Keeps mapping of a loop to estimated weight to enter the loop. |
||
332 | SmallDenseMap<LoopData, uint32_t> EstimatedLoopWeight; |
||
333 | |||
334 | /// Helper to construct LoopBlock for \p BB. |
||
335 | LoopBlock getLoopBlock(const BasicBlock *BB) const { |
||
336 | return LoopBlock(BB, *LI, *SccI.get()); |
||
337 | } |
||
338 | |||
339 | /// Returns true if destination block belongs to some loop and source block is |
||
340 | /// either doesn't belong to any loop or belongs to a loop which is not inner |
||
341 | /// relative to the destination block. |
||
342 | bool isLoopEnteringEdge(const LoopEdge &Edge) const; |
||
343 | /// Returns true if source block belongs to some loop and destination block is |
||
344 | /// either doesn't belong to any loop or belongs to a loop which is not inner |
||
345 | /// relative to the source block. |
||
346 | bool isLoopExitingEdge(const LoopEdge &Edge) const; |
||
347 | /// Returns true if \p Edge is either enters to or exits from some loop, false |
||
348 | /// in all other cases. |
||
349 | bool isLoopEnteringExitingEdge(const LoopEdge &Edge) const; |
||
350 | /// Returns true if source and destination blocks belongs to the same loop and |
||
351 | /// destination block is loop header. |
||
352 | bool isLoopBackEdge(const LoopEdge &Edge) const; |
||
353 | // Fills in \p Enters vector with all "enter" blocks to a loop \LB belongs to. |
||
354 | void getLoopEnterBlocks(const LoopBlock &LB, |
||
355 | SmallVectorImpl<BasicBlock *> &Enters) const; |
||
356 | // Fills in \p Exits vector with all "exit" blocks from a loop \LB belongs to. |
||
357 | void getLoopExitBlocks(const LoopBlock &LB, |
||
358 | SmallVectorImpl<BasicBlock *> &Exits) const; |
||
359 | |||
360 | /// Returns estimated weight for \p BB. std::nullopt if \p BB has no estimated |
||
361 | /// weight. |
||
362 | std::optional<uint32_t> getEstimatedBlockWeight(const BasicBlock *BB) const; |
||
363 | |||
364 | /// Returns estimated weight to enter \p L. In other words it is weight of |
||
365 | /// loop's header block not scaled by trip count. Returns std::nullopt if \p L |
||
366 | /// has no no estimated weight. |
||
367 | std::optional<uint32_t> getEstimatedLoopWeight(const LoopData &L) const; |
||
368 | |||
369 | /// Return estimated weight for \p Edge. Returns std::nullopt if estimated |
||
370 | /// weight is unknown. |
||
371 | std::optional<uint32_t> getEstimatedEdgeWeight(const LoopEdge &Edge) const; |
||
372 | |||
373 | /// Iterates over all edges leading from \p SrcBB to \p Successors and |
||
374 | /// returns maximum of all estimated weights. If at least one edge has unknown |
||
375 | /// estimated weight std::nullopt is returned. |
||
376 | template <class IterT> |
||
377 | std::optional<uint32_t> |
||
378 | getMaxEstimatedEdgeWeight(const LoopBlock &SrcBB, |
||
379 | iterator_range<IterT> Successors) const; |
||
380 | |||
381 | /// If \p LoopBB has no estimated weight then set it to \p BBWeight and |
||
382 | /// return true. Otherwise \p BB's weight remains unchanged and false is |
||
383 | /// returned. In addition all blocks/loops that might need their weight to be |
||
384 | /// re-estimated are put into BlockWorkList/LoopWorkList. |
||
385 | bool updateEstimatedBlockWeight(LoopBlock &LoopBB, uint32_t BBWeight, |
||
386 | SmallVectorImpl<BasicBlock *> &BlockWorkList, |
||
387 | SmallVectorImpl<LoopBlock> &LoopWorkList); |
||
388 | |||
389 | /// Starting from \p LoopBB (including \p LoopBB itself) propagate \p BBWeight |
||
390 | /// up the domination tree. |
||
391 | void propagateEstimatedBlockWeight(const LoopBlock &LoopBB, DominatorTree *DT, |
||
392 | PostDominatorTree *PDT, uint32_t BBWeight, |
||
393 | SmallVectorImpl<BasicBlock *> &WorkList, |
||
394 | SmallVectorImpl<LoopBlock> &LoopWorkList); |
||
395 | |||
396 | /// Returns block's weight encoded in the IR. |
||
397 | std::optional<uint32_t> getInitialEstimatedBlockWeight(const BasicBlock *BB); |
||
398 | |||
399 | // Computes estimated weights for all blocks in \p F. |
||
400 | void computeEestimateBlockWeight(const Function &F, DominatorTree *DT, |
||
401 | PostDominatorTree *PDT); |
||
402 | |||
403 | /// Based on computed weights by \p computeEstimatedBlockWeight set |
||
404 | /// probabilities on branches. |
||
405 | bool calcEstimatedHeuristics(const BasicBlock *BB); |
||
406 | bool calcMetadataWeights(const BasicBlock *BB); |
||
407 | bool calcPointerHeuristics(const BasicBlock *BB); |
||
408 | bool calcZeroHeuristics(const BasicBlock *BB, const TargetLibraryInfo *TLI); |
||
409 | bool calcFloatingPointHeuristics(const BasicBlock *BB); |
||
410 | }; |
||
411 | |||
412 | /// Analysis pass which computes \c BranchProbabilityInfo. |
||
413 | class BranchProbabilityAnalysis |
||
414 | : public AnalysisInfoMixin<BranchProbabilityAnalysis> { |
||
415 | friend AnalysisInfoMixin<BranchProbabilityAnalysis>; |
||
416 | |||
417 | static AnalysisKey Key; |
||
418 | |||
419 | public: |
||
420 | /// Provide the result type for this analysis pass. |
||
421 | using Result = BranchProbabilityInfo; |
||
422 | |||
423 | /// Run the analysis pass over a function and produce BPI. |
||
424 | BranchProbabilityInfo run(Function &F, FunctionAnalysisManager &AM); |
||
425 | }; |
||
426 | |||
427 | /// Printer pass for the \c BranchProbabilityAnalysis results. |
||
428 | class BranchProbabilityPrinterPass |
||
429 | : public PassInfoMixin<BranchProbabilityPrinterPass> { |
||
430 | raw_ostream &OS; |
||
431 | |||
432 | public: |
||
433 | explicit BranchProbabilityPrinterPass(raw_ostream &OS) : OS(OS) {} |
||
434 | |||
435 | PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); |
||
436 | }; |
||
437 | |||
438 | /// Legacy analysis pass which computes \c BranchProbabilityInfo. |
||
439 | class BranchProbabilityInfoWrapperPass : public FunctionPass { |
||
440 | BranchProbabilityInfo BPI; |
||
441 | |||
442 | public: |
||
443 | static char ID; |
||
444 | |||
445 | BranchProbabilityInfoWrapperPass(); |
||
446 | |||
447 | BranchProbabilityInfo &getBPI() { return BPI; } |
||
448 | const BranchProbabilityInfo &getBPI() const { return BPI; } |
||
449 | |||
450 | void getAnalysisUsage(AnalysisUsage &AU) const override; |
||
451 | bool runOnFunction(Function &F) override; |
||
452 | void releaseMemory() override; |
||
453 | void print(raw_ostream &OS, const Module *M = nullptr) const override; |
||
454 | }; |
||
455 | |||
456 | } // end namespace llvm |
||
457 | |||
458 | #endif // LLVM_ANALYSIS_BRANCHPROBABILITYINFO_H |