BlockFrequencyInfo.cpp 12 KB

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