191bc56edSDimitry Andric //===- MachineBlockFrequencyInfo.cpp - MBB Frequency Analysis -------------===//
26122f3e6SDimitry Andric //
36122f3e6SDimitry Andric //                     The LLVM Compiler Infrastructure
46122f3e6SDimitry Andric //
56122f3e6SDimitry Andric // This file is distributed under the University of Illinois Open Source
66122f3e6SDimitry Andric // License. See LICENSE.TXT for details.
76122f3e6SDimitry Andric //
86122f3e6SDimitry Andric //===----------------------------------------------------------------------===//
96122f3e6SDimitry Andric //
106122f3e6SDimitry Andric // Loops should be simplified before this analysis.
116122f3e6SDimitry Andric //
126122f3e6SDimitry Andric //===----------------------------------------------------------------------===//
136122f3e6SDimitry Andric 
146122f3e6SDimitry Andric #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
15*2cab237bSDimitry Andric #include "llvm/ADT/DenseMap.h"
16*2cab237bSDimitry Andric #include "llvm/ADT/None.h"
17*2cab237bSDimitry Andric #include "llvm/ADT/iterator.h"
1891bc56edSDimitry Andric #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
19*2cab237bSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
206122f3e6SDimitry Andric #include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
2191bc56edSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
2291bc56edSDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
23*2cab237bSDimitry Andric #include "llvm/Pass.h"
2491bc56edSDimitry Andric #include "llvm/Support/CommandLine.h"
2591bc56edSDimitry Andric #include "llvm/Support/GraphWriter.h"
26*2cab237bSDimitry Andric #include <string>
276122f3e6SDimitry Andric 
286122f3e6SDimitry Andric using namespace llvm;
296122f3e6SDimitry Andric 
30302affcbSDimitry Andric #define DEBUG_TYPE "machine-block-freq"
3191bc56edSDimitry Andric 
323ca95b02SDimitry Andric static cl::opt<GVDAGType> ViewMachineBlockFreqPropagationDAG(
333ca95b02SDimitry Andric     "view-machine-block-freq-propagation-dags", cl::Hidden,
3491bc56edSDimitry Andric     cl::desc("Pop up a window to show a dag displaying how machine block "
3591bc56edSDimitry Andric              "frequencies propagate through the CFG."),
363ca95b02SDimitry Andric     cl::values(clEnumValN(GVDT_None, "none", "do not display graphs."),
373ca95b02SDimitry Andric                clEnumValN(GVDT_Fraction, "fraction",
383ca95b02SDimitry Andric                           "display a graph using the "
3991bc56edSDimitry Andric                           "fractional block frequency representation."),
403ca95b02SDimitry Andric                clEnumValN(GVDT_Integer, "integer",
413ca95b02SDimitry Andric                           "display a graph using the raw "
4291bc56edSDimitry Andric                           "integer fractional block frequency representation."),
433ca95b02SDimitry Andric                clEnumValN(GVDT_Count, "count", "display a graph using the real "
44d88c1a5aSDimitry Andric                                                "profile count if available.")));
45*2cab237bSDimitry Andric 
467a7e6055SDimitry Andric // Similar option above, but used to control BFI display only after MBP pass
477a7e6055SDimitry Andric cl::opt<GVDAGType> ViewBlockLayoutWithBFI(
487a7e6055SDimitry Andric     "view-block-layout-with-bfi", cl::Hidden,
497a7e6055SDimitry Andric     cl::desc(
507a7e6055SDimitry Andric         "Pop up a window to show a dag displaying MBP layout and associated "
517a7e6055SDimitry Andric         "block frequencies of the CFG."),
527a7e6055SDimitry Andric     cl::values(clEnumValN(GVDT_None, "none", "do not display graphs."),
537a7e6055SDimitry Andric                clEnumValN(GVDT_Fraction, "fraction",
547a7e6055SDimitry Andric                           "display a graph using the "
557a7e6055SDimitry Andric                           "fractional block frequency representation."),
567a7e6055SDimitry Andric                clEnumValN(GVDT_Integer, "integer",
577a7e6055SDimitry Andric                           "display a graph using the raw "
587a7e6055SDimitry Andric                           "integer fractional block frequency representation."),
597a7e6055SDimitry Andric                clEnumValN(GVDT_Count, "count",
607a7e6055SDimitry Andric                           "display a graph using the real "
617a7e6055SDimitry Andric                           "profile count if available.")));
6291bc56edSDimitry Andric 
637a7e6055SDimitry Andric // Command line option to specify the name of the function for CFG dump
647a7e6055SDimitry Andric // Defined in Analysis/BlockFrequencyInfo.cpp:  -view-bfi-func-name=
653ca95b02SDimitry Andric extern cl::opt<std::string> ViewBlockFreqFuncName;
66*2cab237bSDimitry Andric 
677a7e6055SDimitry Andric // Command line option to specify hot frequency threshold.
687a7e6055SDimitry Andric // Defined in Analysis/BlockFrequencyInfo.cpp:  -view-hot-freq-perc=
693ca95b02SDimitry Andric extern cl::opt<unsigned> ViewHotFreqPercent;
703ca95b02SDimitry Andric 
71*2cab237bSDimitry Andric static cl::opt<bool> PrintMachineBlockFreq(
72*2cab237bSDimitry Andric     "print-machine-bfi", cl::init(false), cl::Hidden,
73*2cab237bSDimitry Andric     cl::desc("Print the machine block frequency info."));
74*2cab237bSDimitry Andric 
75*2cab237bSDimitry Andric // Command line option to specify the name of the function for block frequency
76*2cab237bSDimitry Andric // dump. Defined in Analysis/BlockFrequencyInfo.cpp.
77*2cab237bSDimitry Andric extern cl::opt<std::string> PrintBlockFreqFuncName;
78*2cab237bSDimitry Andric 
getGVDT()797a7e6055SDimitry Andric static GVDAGType getGVDT() {
807a7e6055SDimitry Andric   if (ViewBlockLayoutWithBFI != GVDT_None)
817a7e6055SDimitry Andric     return ViewBlockLayoutWithBFI;
827a7e6055SDimitry Andric 
837a7e6055SDimitry Andric   return ViewMachineBlockFreqPropagationDAG;
847a7e6055SDimitry Andric }
857a7e6055SDimitry Andric 
8691bc56edSDimitry Andric namespace llvm {
8791bc56edSDimitry Andric 
883ca95b02SDimitry Andric template <> struct GraphTraits<MachineBlockFrequencyInfo *> {
89*2cab237bSDimitry Andric   using NodeRef = const MachineBasicBlock *;
90*2cab237bSDimitry Andric   using ChildIteratorType = MachineBasicBlock::const_succ_iterator;
91*2cab237bSDimitry Andric   using nodes_iterator = pointer_iterator<MachineFunction::const_iterator>;
9291bc56edSDimitry Andric 
getEntryNodellvm::GraphTraits93d88c1a5aSDimitry Andric   static NodeRef getEntryNode(const MachineBlockFrequencyInfo *G) {
947d523365SDimitry Andric     return &G->getFunction()->front();
9591bc56edSDimitry Andric   }
9691bc56edSDimitry Andric 
child_beginllvm::GraphTraits97d88c1a5aSDimitry Andric   static ChildIteratorType child_begin(const NodeRef N) {
9891bc56edSDimitry Andric     return N->succ_begin();
9991bc56edSDimitry Andric   }
10091bc56edSDimitry Andric 
child_endllvm::GraphTraits101d88c1a5aSDimitry Andric   static ChildIteratorType child_end(const NodeRef N) { return N->succ_end(); }
10291bc56edSDimitry Andric 
nodes_beginllvm::GraphTraits10391bc56edSDimitry Andric   static nodes_iterator nodes_begin(const MachineBlockFrequencyInfo *G) {
104d88c1a5aSDimitry Andric     return nodes_iterator(G->getFunction()->begin());
10591bc56edSDimitry Andric   }
10691bc56edSDimitry Andric 
nodes_endllvm::GraphTraits10791bc56edSDimitry Andric   static nodes_iterator nodes_end(const MachineBlockFrequencyInfo *G) {
108d88c1a5aSDimitry Andric     return nodes_iterator(G->getFunction()->end());
10991bc56edSDimitry Andric   }
11091bc56edSDimitry Andric };
11191bc56edSDimitry Andric 
112*2cab237bSDimitry Andric using MBFIDOTGraphTraitsBase =
113*2cab237bSDimitry Andric     BFIDOTGraphTraitsBase<MachineBlockFrequencyInfo,
114*2cab237bSDimitry Andric                           MachineBranchProbabilityInfo>;
115*2cab237bSDimitry Andric 
11691bc56edSDimitry Andric template <>
1173ca95b02SDimitry Andric struct DOTGraphTraits<MachineBlockFrequencyInfo *>
1183ca95b02SDimitry Andric     : public MBFIDOTGraphTraitsBase {
119*2cab237bSDimitry Andric   const MachineFunction *CurFunc = nullptr;
1207a7e6055SDimitry Andric   DenseMap<const MachineBasicBlock *, int> LayoutOrderMap;
12191bc56edSDimitry Andric 
DOTGraphTraitsllvm::DOTGraphTraits122*2cab237bSDimitry Andric   explicit DOTGraphTraits(bool isSimple = false)
123*2cab237bSDimitry Andric       : MBFIDOTGraphTraitsBase(isSimple) {}
124*2cab237bSDimitry Andric 
getNodeLabelllvm::DOTGraphTraits12591bc56edSDimitry Andric   std::string getNodeLabel(const MachineBasicBlock *Node,
12691bc56edSDimitry Andric                            const MachineBlockFrequencyInfo *Graph) {
1277a7e6055SDimitry Andric     int layout_order = -1;
1287a7e6055SDimitry Andric     // Attach additional ordering information if 'isSimple' is false.
1297a7e6055SDimitry Andric     if (!isSimple()) {
1307a7e6055SDimitry Andric       const MachineFunction *F = Node->getParent();
1317a7e6055SDimitry Andric       if (!CurFunc || F != CurFunc) {
1327a7e6055SDimitry Andric         if (CurFunc)
1337a7e6055SDimitry Andric           LayoutOrderMap.clear();
1347a7e6055SDimitry Andric 
1357a7e6055SDimitry Andric         CurFunc = F;
1367a7e6055SDimitry Andric         int O = 0;
1377a7e6055SDimitry Andric         for (auto MBI = F->begin(); MBI != F->end(); ++MBI, ++O) {
1387a7e6055SDimitry Andric           LayoutOrderMap[&*MBI] = O;
1397a7e6055SDimitry Andric         }
1407a7e6055SDimitry Andric       }
1417a7e6055SDimitry Andric       layout_order = LayoutOrderMap[Node];
1427a7e6055SDimitry Andric     }
1437a7e6055SDimitry Andric     return MBFIDOTGraphTraitsBase::getNodeLabel(Node, Graph, getGVDT(),
1447a7e6055SDimitry Andric                                                 layout_order);
14591bc56edSDimitry Andric   }
14691bc56edSDimitry Andric 
getNodeAttributesllvm::DOTGraphTraits1473ca95b02SDimitry Andric   std::string getNodeAttributes(const MachineBasicBlock *Node,
1483ca95b02SDimitry Andric                                 const MachineBlockFrequencyInfo *Graph) {
1493ca95b02SDimitry Andric     return MBFIDOTGraphTraitsBase::getNodeAttributes(Node, Graph,
1503ca95b02SDimitry Andric                                                      ViewHotFreqPercent);
1513ca95b02SDimitry Andric   }
1523ca95b02SDimitry Andric 
getEdgeAttributesllvm::DOTGraphTraits1533ca95b02SDimitry Andric   std::string getEdgeAttributes(const MachineBasicBlock *Node, EdgeIter EI,
1543ca95b02SDimitry Andric                                 const MachineBlockFrequencyInfo *MBFI) {
1553ca95b02SDimitry Andric     return MBFIDOTGraphTraitsBase::getEdgeAttributes(
1563ca95b02SDimitry Andric         Node, EI, MBFI, MBFI->getMBPI(), ViewHotFreqPercent);
15791bc56edSDimitry Andric   }
15891bc56edSDimitry Andric };
15991bc56edSDimitry Andric 
16091bc56edSDimitry Andric } // end namespace llvm
16191bc56edSDimitry Andric 
162302affcbSDimitry Andric INITIALIZE_PASS_BEGIN(MachineBlockFrequencyInfo, DEBUG_TYPE,
1636122f3e6SDimitry Andric                       "Machine Block Frequency Analysis", true, true)
1646122f3e6SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
16591bc56edSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
166302affcbSDimitry Andric INITIALIZE_PASS_END(MachineBlockFrequencyInfo, DEBUG_TYPE,
1676122f3e6SDimitry Andric                     "Machine Block Frequency Analysis", true, true)
1686122f3e6SDimitry Andric 
1696122f3e6SDimitry Andric char MachineBlockFrequencyInfo::ID = 0;
1706122f3e6SDimitry Andric 
MachineBlockFrequencyInfo()1713ca95b02SDimitry Andric MachineBlockFrequencyInfo::MachineBlockFrequencyInfo()
1723ca95b02SDimitry Andric     : MachineFunctionPass(ID) {
1736122f3e6SDimitry Andric   initializeMachineBlockFrequencyInfoPass(*PassRegistry::getPassRegistry());
1746122f3e6SDimitry Andric }
1756122f3e6SDimitry Andric 
176*2cab237bSDimitry Andric MachineBlockFrequencyInfo::~MachineBlockFrequencyInfo() = default;
1776122f3e6SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const1786122f3e6SDimitry Andric void MachineBlockFrequencyInfo::getAnalysisUsage(AnalysisUsage &AU) const {
1796122f3e6SDimitry Andric   AU.addRequired<MachineBranchProbabilityInfo>();
18091bc56edSDimitry Andric   AU.addRequired<MachineLoopInfo>();
1816122f3e6SDimitry Andric   AU.setPreservesAll();
1826122f3e6SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
1836122f3e6SDimitry Andric }
1846122f3e6SDimitry Andric 
calculate(const MachineFunction & F,const MachineBranchProbabilityInfo & MBPI,const MachineLoopInfo & MLI)1857a7e6055SDimitry Andric void MachineBlockFrequencyInfo::calculate(
1867a7e6055SDimitry Andric     const MachineFunction &F, const MachineBranchProbabilityInfo &MBPI,
1877a7e6055SDimitry Andric     const MachineLoopInfo &MLI) {
1887a7e6055SDimitry Andric   if (!MBFI)
1897a7e6055SDimitry Andric     MBFI.reset(new ImplType);
1907a7e6055SDimitry Andric   MBFI->calculate(F, MBPI, MLI);
1917a7e6055SDimitry Andric   if (ViewMachineBlockFreqPropagationDAG != GVDT_None &&
1927a7e6055SDimitry Andric       (ViewBlockFreqFuncName.empty() ||
1937a7e6055SDimitry Andric        F.getName().equals(ViewBlockFreqFuncName))) {
1947a7e6055SDimitry Andric     view("MachineBlockFrequencyDAGS." + F.getName());
1957a7e6055SDimitry Andric   }
196*2cab237bSDimitry Andric   if (PrintMachineBlockFreq &&
197*2cab237bSDimitry Andric       (PrintBlockFreqFuncName.empty() ||
198*2cab237bSDimitry Andric        F.getName().equals(PrintBlockFreqFuncName))) {
199*2cab237bSDimitry Andric     MBFI->print(dbgs());
200*2cab237bSDimitry Andric   }
2017a7e6055SDimitry Andric }
2027a7e6055SDimitry Andric 
runOnMachineFunction(MachineFunction & F)2036122f3e6SDimitry Andric bool MachineBlockFrequencyInfo::runOnMachineFunction(MachineFunction &F) {
20491bc56edSDimitry Andric   MachineBranchProbabilityInfo &MBPI =
20591bc56edSDimitry Andric       getAnalysis<MachineBranchProbabilityInfo>();
20691bc56edSDimitry Andric   MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
2077a7e6055SDimitry Andric   calculate(F, MBPI, MLI);
2086122f3e6SDimitry Andric   return false;
2096122f3e6SDimitry Andric }
2106122f3e6SDimitry Andric 
releaseMemory()21191bc56edSDimitry Andric void MachineBlockFrequencyInfo::releaseMemory() { MBFI.reset(); }
21291bc56edSDimitry Andric 
21391bc56edSDimitry Andric /// Pop up a ghostview window with the current block frequency propagation
21491bc56edSDimitry Andric /// rendered using dot.
view(const Twine & Name,bool isSimple) const2157a7e6055SDimitry Andric void MachineBlockFrequencyInfo::view(const Twine &Name, bool isSimple) const {
21691bc56edSDimitry Andric   // This code is only for debugging.
2177a7e6055SDimitry Andric   ViewGraph(const_cast<MachineBlockFrequencyInfo *>(this), Name, isSimple);
21891bc56edSDimitry Andric }
21991bc56edSDimitry Andric 
2203ca95b02SDimitry Andric BlockFrequency
getBlockFreq(const MachineBasicBlock * MBB) const2213ca95b02SDimitry Andric MachineBlockFrequencyInfo::getBlockFreq(const MachineBasicBlock *MBB) const {
22291bc56edSDimitry Andric   return MBFI ? MBFI->getBlockFreq(MBB) : 0;
22391bc56edSDimitry Andric }
22491bc56edSDimitry Andric 
getBlockProfileCount(const MachineBasicBlock * MBB) const2253ca95b02SDimitry Andric Optional<uint64_t> MachineBlockFrequencyInfo::getBlockProfileCount(
2263ca95b02SDimitry Andric     const MachineBasicBlock *MBB) const {
227*2cab237bSDimitry Andric   const Function &F = MBFI->getFunction()->getFunction();
228*2cab237bSDimitry Andric   return MBFI ? MBFI->getBlockProfileCount(F, MBB) : None;
2293ca95b02SDimitry Andric }
2303ca95b02SDimitry Andric 
231d88c1a5aSDimitry Andric Optional<uint64_t>
getProfileCountFromFreq(uint64_t Freq) const232d88c1a5aSDimitry Andric MachineBlockFrequencyInfo::getProfileCountFromFreq(uint64_t Freq) const {
233*2cab237bSDimitry Andric   const Function &F = MBFI->getFunction()->getFunction();
234*2cab237bSDimitry Andric   return MBFI ? MBFI->getProfileCountFromFreq(F, Freq) : None;
235*2cab237bSDimitry Andric }
236*2cab237bSDimitry Andric 
237*2cab237bSDimitry Andric bool
isIrrLoopHeader(const MachineBasicBlock * MBB)238*2cab237bSDimitry Andric MachineBlockFrequencyInfo::isIrrLoopHeader(const MachineBasicBlock *MBB) {
239*2cab237bSDimitry Andric   assert(MBFI && "Expected analysis to be available");
240*2cab237bSDimitry Andric   return MBFI->isIrrLoopHeader(MBB);
241d88c1a5aSDimitry Andric }
242d88c1a5aSDimitry Andric 
getFunction() const24391bc56edSDimitry Andric const MachineFunction *MachineBlockFrequencyInfo::getFunction() const {
24491bc56edSDimitry Andric   return MBFI ? MBFI->getFunction() : nullptr;
24591bc56edSDimitry Andric }
24691bc56edSDimitry Andric 
getMBPI() const2473ca95b02SDimitry Andric const MachineBranchProbabilityInfo *MachineBlockFrequencyInfo::getMBPI() const {
2483ca95b02SDimitry Andric   return MBFI ? &MBFI->getBPI() : nullptr;
2493ca95b02SDimitry Andric }
2503ca95b02SDimitry Andric 
25191bc56edSDimitry Andric raw_ostream &
printBlockFreq(raw_ostream & OS,const BlockFrequency Freq) const25291bc56edSDimitry Andric MachineBlockFrequencyInfo::printBlockFreq(raw_ostream &OS,
25391bc56edSDimitry Andric                                           const BlockFrequency Freq) const {
25491bc56edSDimitry Andric   return MBFI ? MBFI->printBlockFreq(OS, Freq) : OS;
25591bc56edSDimitry Andric }
25691bc56edSDimitry Andric 
25791bc56edSDimitry Andric raw_ostream &
printBlockFreq(raw_ostream & OS,const MachineBasicBlock * MBB) const25891bc56edSDimitry Andric MachineBlockFrequencyInfo::printBlockFreq(raw_ostream &OS,
25991bc56edSDimitry Andric                                           const MachineBasicBlock *MBB) const {
26091bc56edSDimitry Andric   return MBFI ? MBFI->printBlockFreq(OS, MBB) : OS;
26191bc56edSDimitry Andric }
26291bc56edSDimitry Andric 
getEntryFreq() const26391bc56edSDimitry Andric uint64_t MachineBlockFrequencyInfo::getEntryFreq() const {
26491bc56edSDimitry Andric   return MBFI ? MBFI->getEntryFreq() : 0;
2656122f3e6SDimitry Andric }
266