1 //===- BlockFrequencyInfo.cpp - Block Frequency Analysis ------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Loops should be simplified before this analysis. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Analysis/BlockFrequencyInfo.h" 15 #include "llvm/ADT/APInt.h" 16 #include "llvm/ADT/None.h" 17 #include "llvm/ADT/iterator.h" 18 #include "llvm/Analysis/BlockFrequencyInfoImpl.h" 19 #include "llvm/Analysis/BranchProbabilityInfo.h" 20 #include "llvm/Analysis/LoopInfo.h" 21 #include "llvm/IR/CFG.h" 22 #include "llvm/IR/Function.h" 23 #include "llvm/IR/PassManager.h" 24 #include "llvm/Pass.h" 25 #include "llvm/Support/CommandLine.h" 26 #include "llvm/Support/GraphWriter.h" 27 #include "llvm/Support/raw_ostream.h" 28 #include <algorithm> 29 #include <cassert> 30 #include <string> 31 32 using namespace llvm; 33 34 #define DEBUG_TYPE "block-freq" 35 36 static cl::opt<GVDAGType> ViewBlockFreqPropagationDAG( 37 "view-block-freq-propagation-dags", cl::Hidden, 38 cl::desc("Pop up a window to show a dag displaying how block " 39 "frequencies propagation through the CFG."), 40 cl::values(clEnumValN(GVDT_None, "none", "do not display graphs."), 41 clEnumValN(GVDT_Fraction, "fraction", 42 "display a graph using the " 43 "fractional block frequency representation."), 44 clEnumValN(GVDT_Integer, "integer", 45 "display a graph using the raw " 46 "integer fractional block frequency representation."), 47 clEnumValN(GVDT_Count, "count", "display a graph using the real " 48 "profile count if available."))); 49 50 cl::opt<std::string> 51 ViewBlockFreqFuncName("view-bfi-func-name", cl::Hidden, 52 cl::desc("The option to specify " 53 "the name of the function " 54 "whose CFG will be displayed.")); 55 56 cl::opt<unsigned> 57 ViewHotFreqPercent("view-hot-freq-percent", cl::init(10), cl::Hidden, 58 cl::desc("An integer in percent used to specify " 59 "the hot blocks/edges to be displayed " 60 "in red: a block or edge whose frequency " 61 "is no less than the max frequency of the " 62 "function multiplied by this percent.")); 63 64 // Command line option to turn on CFG dot dump after profile annotation. 65 cl::opt<bool> 66 PGOViewCounts("pgo-view-counts", cl::init(false), cl::Hidden, 67 cl::desc("A boolean option to show CFG dag with " 68 "block profile counts and branch probabilities " 69 "right after PGO profile annotation step. The " 70 "profile counts are computed using branch " 71 "probabilities from the runtime profile data and " 72 "block frequency propagation algorithm. To view " 73 "the raw counts from the profile, use option " 74 "-pgo-view-raw-counts instead. To limit graph " 75 "display to only one function, use filtering option " 76 "-view-bfi-func-name.")); 77 78 namespace llvm { 79 80 static GVDAGType getGVDT() { 81 if (PGOViewCounts) 82 return GVDT_Count; 83 return ViewBlockFreqPropagationDAG; 84 } 85 86 template <> 87 struct GraphTraits<BlockFrequencyInfo *> { 88 using NodeRef = const BasicBlock *; 89 using ChildIteratorType = succ_const_iterator; 90 using nodes_iterator = pointer_iterator<Function::const_iterator>; 91 92 static NodeRef getEntryNode(const BlockFrequencyInfo *G) { 93 return &G->getFunction()->front(); 94 } 95 96 static ChildIteratorType child_begin(const NodeRef N) { 97 return succ_begin(N); 98 } 99 100 static ChildIteratorType child_end(const NodeRef N) { return succ_end(N); } 101 102 static nodes_iterator nodes_begin(const BlockFrequencyInfo *G) { 103 return nodes_iterator(G->getFunction()->begin()); 104 } 105 106 static nodes_iterator nodes_end(const BlockFrequencyInfo *G) { 107 return nodes_iterator(G->getFunction()->end()); 108 } 109 }; 110 111 using BFIDOTGTraitsBase = 112 BFIDOTGraphTraitsBase<BlockFrequencyInfo, BranchProbabilityInfo>; 113 114 template <> 115 struct DOTGraphTraits<BlockFrequencyInfo *> : public BFIDOTGTraitsBase { 116 explicit DOTGraphTraits(bool isSimple = false) 117 : BFIDOTGTraitsBase(isSimple) {} 118 119 std::string getNodeLabel(const BasicBlock *Node, 120 const BlockFrequencyInfo *Graph) { 121 122 return BFIDOTGTraitsBase::getNodeLabel(Node, Graph, getGVDT()); 123 } 124 125 std::string getNodeAttributes(const BasicBlock *Node, 126 const BlockFrequencyInfo *Graph) { 127 return BFIDOTGTraitsBase::getNodeAttributes(Node, Graph, 128 ViewHotFreqPercent); 129 } 130 131 std::string getEdgeAttributes(const BasicBlock *Node, EdgeIter EI, 132 const BlockFrequencyInfo *BFI) { 133 return BFIDOTGTraitsBase::getEdgeAttributes(Node, EI, BFI, BFI->getBPI(), 134 ViewHotFreqPercent); 135 } 136 }; 137 138 } // end namespace llvm 139 140 BlockFrequencyInfo::BlockFrequencyInfo() = default; 141 142 BlockFrequencyInfo::BlockFrequencyInfo(const Function &F, 143 const BranchProbabilityInfo &BPI, 144 const LoopInfo &LI) { 145 calculate(F, BPI, LI); 146 } 147 148 BlockFrequencyInfo::BlockFrequencyInfo(BlockFrequencyInfo &&Arg) 149 : BFI(std::move(Arg.BFI)) {} 150 151 BlockFrequencyInfo &BlockFrequencyInfo::operator=(BlockFrequencyInfo &&RHS) { 152 releaseMemory(); 153 BFI = std::move(RHS.BFI); 154 return *this; 155 } 156 157 // Explicitly define the default constructor otherwise it would be implicitly 158 // defined at the first ODR-use which is the BFI member in the 159 // LazyBlockFrequencyInfo header. The dtor needs the BlockFrequencyInfoImpl 160 // template instantiated which is not available in the header. 161 BlockFrequencyInfo::~BlockFrequencyInfo() = default; 162 163 bool BlockFrequencyInfo::invalidate(Function &F, const PreservedAnalyses &PA, 164 FunctionAnalysisManager::Invalidator &) { 165 // Check whether the analysis, all analyses on functions, or the function's 166 // CFG have been preserved. 167 auto PAC = PA.getChecker<BlockFrequencyAnalysis>(); 168 return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>() || 169 PAC.preservedSet<CFGAnalyses>()); 170 } 171 172 void BlockFrequencyInfo::calculate(const Function &F, 173 const BranchProbabilityInfo &BPI, 174 const LoopInfo &LI) { 175 if (!BFI) 176 BFI.reset(new ImplType); 177 BFI->calculate(F, BPI, LI); 178 if (ViewBlockFreqPropagationDAG != GVDT_None && 179 (ViewBlockFreqFuncName.empty() || 180 F.getName().equals(ViewBlockFreqFuncName))) { 181 view(); 182 } 183 } 184 185 BlockFrequency BlockFrequencyInfo::getBlockFreq(const BasicBlock *BB) const { 186 return BFI ? BFI->getBlockFreq(BB) : 0; 187 } 188 189 Optional<uint64_t> 190 BlockFrequencyInfo::getBlockProfileCount(const BasicBlock *BB) const { 191 if (!BFI) 192 return None; 193 194 return BFI->getBlockProfileCount(*getFunction(), BB); 195 } 196 197 Optional<uint64_t> 198 BlockFrequencyInfo::getProfileCountFromFreq(uint64_t Freq) const { 199 if (!BFI) 200 return None; 201 return BFI->getProfileCountFromFreq(*getFunction(), Freq); 202 } 203 204 void BlockFrequencyInfo::setBlockFreq(const BasicBlock *BB, uint64_t Freq) { 205 assert(BFI && "Expected analysis to be available"); 206 BFI->setBlockFreq(BB, Freq); 207 } 208 209 void BlockFrequencyInfo::setBlockFreqAndScale( 210 const BasicBlock *ReferenceBB, uint64_t Freq, 211 SmallPtrSetImpl<BasicBlock *> &BlocksToScale) { 212 assert(BFI && "Expected analysis to be available"); 213 // Use 128 bits APInt to avoid overflow. 214 APInt NewFreq(128, Freq); 215 APInt OldFreq(128, BFI->getBlockFreq(ReferenceBB).getFrequency()); 216 APInt BBFreq(128, 0); 217 for (auto *BB : BlocksToScale) { 218 BBFreq = BFI->getBlockFreq(BB).getFrequency(); 219 // Multiply first by NewFreq and then divide by OldFreq 220 // to minimize loss of precision. 221 BBFreq *= NewFreq; 222 // udiv is an expensive operation in the general case. If this ends up being 223 // a hot spot, one of the options proposed in 224 // https://reviews.llvm.org/D28535#650071 could be used to avoid this. 225 BBFreq = BBFreq.udiv(OldFreq); 226 BFI->setBlockFreq(BB, BBFreq.getLimitedValue()); 227 } 228 BFI->setBlockFreq(ReferenceBB, Freq); 229 } 230 231 /// Pop up a ghostview window with the current block frequency propagation 232 /// rendered using dot. 233 void BlockFrequencyInfo::view() const { 234 ViewGraph(const_cast<BlockFrequencyInfo *>(this), "BlockFrequencyDAGs"); 235 } 236 237 const Function *BlockFrequencyInfo::getFunction() const { 238 return BFI ? BFI->getFunction() : nullptr; 239 } 240 241 const BranchProbabilityInfo *BlockFrequencyInfo::getBPI() const { 242 return BFI ? &BFI->getBPI() : nullptr; 243 } 244 245 raw_ostream &BlockFrequencyInfo:: 246 printBlockFreq(raw_ostream &OS, const BlockFrequency Freq) const { 247 return BFI ? BFI->printBlockFreq(OS, Freq) : OS; 248 } 249 250 raw_ostream & 251 BlockFrequencyInfo::printBlockFreq(raw_ostream &OS, 252 const BasicBlock *BB) const { 253 return BFI ? BFI->printBlockFreq(OS, BB) : OS; 254 } 255 256 uint64_t BlockFrequencyInfo::getEntryFreq() const { 257 return BFI ? BFI->getEntryFreq() : 0; 258 } 259 260 void BlockFrequencyInfo::releaseMemory() { BFI.reset(); } 261 262 void BlockFrequencyInfo::print(raw_ostream &OS) const { 263 if (BFI) 264 BFI->print(OS); 265 } 266 267 INITIALIZE_PASS_BEGIN(BlockFrequencyInfoWrapperPass, "block-freq", 268 "Block Frequency Analysis", true, true) 269 INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfoWrapperPass) 270 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) 271 INITIALIZE_PASS_END(BlockFrequencyInfoWrapperPass, "block-freq", 272 "Block Frequency Analysis", true, true) 273 274 char BlockFrequencyInfoWrapperPass::ID = 0; 275 276 BlockFrequencyInfoWrapperPass::BlockFrequencyInfoWrapperPass() 277 : FunctionPass(ID) { 278 initializeBlockFrequencyInfoWrapperPassPass(*PassRegistry::getPassRegistry()); 279 } 280 281 BlockFrequencyInfoWrapperPass::~BlockFrequencyInfoWrapperPass() = default; 282 283 void BlockFrequencyInfoWrapperPass::print(raw_ostream &OS, 284 const Module *) const { 285 BFI.print(OS); 286 } 287 288 void BlockFrequencyInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { 289 AU.addRequired<BranchProbabilityInfoWrapperPass>(); 290 AU.addRequired<LoopInfoWrapperPass>(); 291 AU.setPreservesAll(); 292 } 293 294 void BlockFrequencyInfoWrapperPass::releaseMemory() { BFI.releaseMemory(); } 295 296 bool BlockFrequencyInfoWrapperPass::runOnFunction(Function &F) { 297 BranchProbabilityInfo &BPI = 298 getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI(); 299 LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); 300 BFI.calculate(F, BPI, LI); 301 return false; 302 } 303 304 AnalysisKey BlockFrequencyAnalysis::Key; 305 BlockFrequencyInfo BlockFrequencyAnalysis::run(Function &F, 306 FunctionAnalysisManager &AM) { 307 BlockFrequencyInfo BFI; 308 BFI.calculate(F, AM.getResult<BranchProbabilityAnalysis>(F), 309 AM.getResult<LoopAnalysis>(F)); 310 return BFI; 311 } 312 313 PreservedAnalyses 314 BlockFrequencyPrinterPass::run(Function &F, FunctionAnalysisManager &AM) { 315 OS << "Printing analysis results of BFI for function " 316 << "'" << F.getName() << "':" 317 << "\n"; 318 AM.getResult<BlockFrequencyAnalysis>(F).print(OS); 319 return PreservedAnalyses::all(); 320 } 321