1*91bc56edSDimitry 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*91bc56edSDimitry Andric #include "llvm/Analysis/BlockFrequencyInfoImpl.h" 166122f3e6SDimitry Andric #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" 17*91bc56edSDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 18*91bc56edSDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 19139f7f9bSDimitry Andric #include "llvm/CodeGen/Passes.h" 20139f7f9bSDimitry Andric #include "llvm/InitializePasses.h" 21*91bc56edSDimitry Andric #include "llvm/Support/CommandLine.h" 22*91bc56edSDimitry Andric #include "llvm/Support/Debug.h" 23*91bc56edSDimitry Andric #include "llvm/Support/GraphWriter.h" 246122f3e6SDimitry Andric 256122f3e6SDimitry Andric using namespace llvm; 266122f3e6SDimitry Andric 27*91bc56edSDimitry Andric #define DEBUG_TYPE "block-freq" 28*91bc56edSDimitry Andric 29*91bc56edSDimitry Andric #ifndef NDEBUG 30*91bc56edSDimitry Andric enum GVDAGType { 31*91bc56edSDimitry Andric GVDT_None, 32*91bc56edSDimitry Andric GVDT_Fraction, 33*91bc56edSDimitry Andric GVDT_Integer 34*91bc56edSDimitry Andric }; 35*91bc56edSDimitry Andric 36*91bc56edSDimitry Andric static cl::opt<GVDAGType> 37*91bc56edSDimitry Andric ViewMachineBlockFreqPropagationDAG("view-machine-block-freq-propagation-dags", 38*91bc56edSDimitry Andric cl::Hidden, 39*91bc56edSDimitry Andric cl::desc("Pop up a window to show a dag displaying how machine block " 40*91bc56edSDimitry Andric "frequencies propagate through the CFG."), 41*91bc56edSDimitry Andric cl::values( 42*91bc56edSDimitry Andric clEnumValN(GVDT_None, "none", 43*91bc56edSDimitry Andric "do not display graphs."), 44*91bc56edSDimitry Andric clEnumValN(GVDT_Fraction, "fraction", "display a graph using the " 45*91bc56edSDimitry Andric "fractional block frequency representation."), 46*91bc56edSDimitry Andric clEnumValN(GVDT_Integer, "integer", "display a graph using the raw " 47*91bc56edSDimitry Andric "integer fractional block frequency representation."), 48*91bc56edSDimitry Andric clEnumValEnd)); 49*91bc56edSDimitry Andric 50*91bc56edSDimitry Andric namespace llvm { 51*91bc56edSDimitry Andric 52*91bc56edSDimitry Andric template <> 53*91bc56edSDimitry Andric struct GraphTraits<MachineBlockFrequencyInfo *> { 54*91bc56edSDimitry Andric typedef const MachineBasicBlock NodeType; 55*91bc56edSDimitry Andric typedef MachineBasicBlock::const_succ_iterator ChildIteratorType; 56*91bc56edSDimitry Andric typedef MachineFunction::const_iterator nodes_iterator; 57*91bc56edSDimitry Andric 58*91bc56edSDimitry Andric static inline 59*91bc56edSDimitry Andric const NodeType *getEntryNode(const MachineBlockFrequencyInfo *G) { 60*91bc56edSDimitry Andric return G->getFunction()->begin(); 61*91bc56edSDimitry Andric } 62*91bc56edSDimitry Andric 63*91bc56edSDimitry Andric static ChildIteratorType child_begin(const NodeType *N) { 64*91bc56edSDimitry Andric return N->succ_begin(); 65*91bc56edSDimitry Andric } 66*91bc56edSDimitry Andric 67*91bc56edSDimitry Andric static ChildIteratorType child_end(const NodeType *N) { 68*91bc56edSDimitry Andric return N->succ_end(); 69*91bc56edSDimitry Andric } 70*91bc56edSDimitry Andric 71*91bc56edSDimitry Andric static nodes_iterator nodes_begin(const MachineBlockFrequencyInfo *G) { 72*91bc56edSDimitry Andric return G->getFunction()->begin(); 73*91bc56edSDimitry Andric } 74*91bc56edSDimitry Andric 75*91bc56edSDimitry Andric static nodes_iterator nodes_end(const MachineBlockFrequencyInfo *G) { 76*91bc56edSDimitry Andric return G->getFunction()->end(); 77*91bc56edSDimitry Andric } 78*91bc56edSDimitry Andric }; 79*91bc56edSDimitry Andric 80*91bc56edSDimitry Andric template<> 81*91bc56edSDimitry Andric struct DOTGraphTraits<MachineBlockFrequencyInfo*> : 82*91bc56edSDimitry Andric public DefaultDOTGraphTraits { 83*91bc56edSDimitry Andric explicit DOTGraphTraits(bool isSimple=false) : 84*91bc56edSDimitry Andric DefaultDOTGraphTraits(isSimple) {} 85*91bc56edSDimitry Andric 86*91bc56edSDimitry Andric static std::string getGraphName(const MachineBlockFrequencyInfo *G) { 87*91bc56edSDimitry Andric return G->getFunction()->getName(); 88*91bc56edSDimitry Andric } 89*91bc56edSDimitry Andric 90*91bc56edSDimitry Andric std::string getNodeLabel(const MachineBasicBlock *Node, 91*91bc56edSDimitry Andric const MachineBlockFrequencyInfo *Graph) { 92*91bc56edSDimitry Andric std::string Result; 93*91bc56edSDimitry Andric raw_string_ostream OS(Result); 94*91bc56edSDimitry Andric 95*91bc56edSDimitry Andric OS << Node->getName().str() << ":"; 96*91bc56edSDimitry Andric switch (ViewMachineBlockFreqPropagationDAG) { 97*91bc56edSDimitry Andric case GVDT_Fraction: 98*91bc56edSDimitry Andric Graph->printBlockFreq(OS, Node); 99*91bc56edSDimitry Andric break; 100*91bc56edSDimitry Andric case GVDT_Integer: 101*91bc56edSDimitry Andric OS << Graph->getBlockFreq(Node).getFrequency(); 102*91bc56edSDimitry Andric break; 103*91bc56edSDimitry Andric case GVDT_None: 104*91bc56edSDimitry Andric llvm_unreachable("If we are not supposed to render a graph we should " 105*91bc56edSDimitry Andric "never reach this point."); 106*91bc56edSDimitry Andric } 107*91bc56edSDimitry Andric 108*91bc56edSDimitry Andric return Result; 109*91bc56edSDimitry Andric } 110*91bc56edSDimitry Andric }; 111*91bc56edSDimitry Andric 112*91bc56edSDimitry Andric 113*91bc56edSDimitry Andric } // end namespace llvm 114*91bc56edSDimitry Andric #endif 115*91bc56edSDimitry Andric 1166122f3e6SDimitry Andric INITIALIZE_PASS_BEGIN(MachineBlockFrequencyInfo, "machine-block-freq", 1176122f3e6SDimitry Andric "Machine Block Frequency Analysis", true, true) 1186122f3e6SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo) 119*91bc56edSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) 1206122f3e6SDimitry Andric INITIALIZE_PASS_END(MachineBlockFrequencyInfo, "machine-block-freq", 1216122f3e6SDimitry Andric "Machine Block Frequency Analysis", true, true) 1226122f3e6SDimitry Andric 1236122f3e6SDimitry Andric char MachineBlockFrequencyInfo::ID = 0; 1246122f3e6SDimitry Andric 1256122f3e6SDimitry Andric 126*91bc56edSDimitry Andric MachineBlockFrequencyInfo:: 127*91bc56edSDimitry Andric MachineBlockFrequencyInfo() :MachineFunctionPass(ID) { 1286122f3e6SDimitry Andric initializeMachineBlockFrequencyInfoPass(*PassRegistry::getPassRegistry()); 1296122f3e6SDimitry Andric } 1306122f3e6SDimitry Andric 131*91bc56edSDimitry Andric MachineBlockFrequencyInfo::~MachineBlockFrequencyInfo() {} 1326122f3e6SDimitry Andric 1336122f3e6SDimitry Andric void MachineBlockFrequencyInfo::getAnalysisUsage(AnalysisUsage &AU) const { 1346122f3e6SDimitry Andric AU.addRequired<MachineBranchProbabilityInfo>(); 135*91bc56edSDimitry Andric AU.addRequired<MachineLoopInfo>(); 1366122f3e6SDimitry Andric AU.setPreservesAll(); 1376122f3e6SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 1386122f3e6SDimitry Andric } 1396122f3e6SDimitry Andric 1406122f3e6SDimitry Andric bool MachineBlockFrequencyInfo::runOnMachineFunction(MachineFunction &F) { 141*91bc56edSDimitry Andric MachineBranchProbabilityInfo &MBPI = 142*91bc56edSDimitry Andric getAnalysis<MachineBranchProbabilityInfo>(); 143*91bc56edSDimitry Andric MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>(); 144*91bc56edSDimitry Andric if (!MBFI) 145*91bc56edSDimitry Andric MBFI.reset(new ImplType); 146*91bc56edSDimitry Andric MBFI->doFunction(&F, &MBPI, &MLI); 147*91bc56edSDimitry Andric #ifndef NDEBUG 148*91bc56edSDimitry Andric if (ViewMachineBlockFreqPropagationDAG != GVDT_None) { 149*91bc56edSDimitry Andric view(); 150*91bc56edSDimitry Andric } 151*91bc56edSDimitry Andric #endif 1526122f3e6SDimitry Andric return false; 1536122f3e6SDimitry Andric } 1546122f3e6SDimitry Andric 155*91bc56edSDimitry Andric void MachineBlockFrequencyInfo::releaseMemory() { MBFI.reset(); } 156*91bc56edSDimitry Andric 157*91bc56edSDimitry Andric /// Pop up a ghostview window with the current block frequency propagation 158*91bc56edSDimitry Andric /// rendered using dot. 159*91bc56edSDimitry Andric void MachineBlockFrequencyInfo::view() const { 160*91bc56edSDimitry Andric // This code is only for debugging. 161*91bc56edSDimitry Andric #ifndef NDEBUG 162*91bc56edSDimitry Andric ViewGraph(const_cast<MachineBlockFrequencyInfo *>(this), 163*91bc56edSDimitry Andric "MachineBlockFrequencyDAGs"); 164*91bc56edSDimitry Andric #else 165*91bc56edSDimitry Andric errs() << "MachineBlockFrequencyInfo::view is only available in debug builds " 166*91bc56edSDimitry Andric "on systems with Graphviz or gv!\n"; 167*91bc56edSDimitry Andric #endif // NDEBUG 168*91bc56edSDimitry Andric } 169*91bc56edSDimitry Andric 1706122f3e6SDimitry Andric BlockFrequency MachineBlockFrequencyInfo:: 171dff0c46cSDimitry Andric getBlockFreq(const MachineBasicBlock *MBB) const { 172*91bc56edSDimitry Andric return MBFI ? MBFI->getBlockFreq(MBB) : 0; 173*91bc56edSDimitry Andric } 174*91bc56edSDimitry Andric 175*91bc56edSDimitry Andric const MachineFunction *MachineBlockFrequencyInfo::getFunction() const { 176*91bc56edSDimitry Andric return MBFI ? MBFI->getFunction() : nullptr; 177*91bc56edSDimitry Andric } 178*91bc56edSDimitry Andric 179*91bc56edSDimitry Andric raw_ostream & 180*91bc56edSDimitry Andric MachineBlockFrequencyInfo::printBlockFreq(raw_ostream &OS, 181*91bc56edSDimitry Andric const BlockFrequency Freq) const { 182*91bc56edSDimitry Andric return MBFI ? MBFI->printBlockFreq(OS, Freq) : OS; 183*91bc56edSDimitry Andric } 184*91bc56edSDimitry Andric 185*91bc56edSDimitry Andric raw_ostream & 186*91bc56edSDimitry Andric MachineBlockFrequencyInfo::printBlockFreq(raw_ostream &OS, 187*91bc56edSDimitry Andric const MachineBasicBlock *MBB) const { 188*91bc56edSDimitry Andric return MBFI ? MBFI->printBlockFreq(OS, MBB) : OS; 189*91bc56edSDimitry Andric } 190*91bc56edSDimitry Andric 191*91bc56edSDimitry Andric uint64_t MachineBlockFrequencyInfo::getEntryFreq() const { 192*91bc56edSDimitry Andric return MBFI ? MBFI->getEntryFreq() : 0; 1936122f3e6SDimitry Andric } 194