1*0b57cec5SDimitry Andric //===- MachineBlockFrequencyInfo.cpp - MBB Frequency Analysis -------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // Loops should be simplified before this analysis. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" 14*0b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 15*0b57cec5SDimitry Andric #include "llvm/ADT/None.h" 16*0b57cec5SDimitry Andric #include "llvm/ADT/iterator.h" 17*0b57cec5SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfoImpl.h" 18*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 19*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" 20*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 22*0b57cec5SDimitry Andric #include "llvm/Pass.h" 23*0b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 24*0b57cec5SDimitry Andric #include "llvm/Support/GraphWriter.h" 25*0b57cec5SDimitry Andric #include <string> 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric using namespace llvm; 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric #define DEBUG_TYPE "machine-block-freq" 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric static cl::opt<GVDAGType> ViewMachineBlockFreqPropagationDAG( 32*0b57cec5SDimitry Andric "view-machine-block-freq-propagation-dags", cl::Hidden, 33*0b57cec5SDimitry Andric cl::desc("Pop up a window to show a dag displaying how machine block " 34*0b57cec5SDimitry Andric "frequencies propagate through the CFG."), 35*0b57cec5SDimitry Andric cl::values(clEnumValN(GVDT_None, "none", "do not display graphs."), 36*0b57cec5SDimitry Andric clEnumValN(GVDT_Fraction, "fraction", 37*0b57cec5SDimitry Andric "display a graph using the " 38*0b57cec5SDimitry Andric "fractional block frequency representation."), 39*0b57cec5SDimitry Andric clEnumValN(GVDT_Integer, "integer", 40*0b57cec5SDimitry Andric "display a graph using the raw " 41*0b57cec5SDimitry Andric "integer fractional block frequency representation."), 42*0b57cec5SDimitry Andric clEnumValN(GVDT_Count, "count", "display a graph using the real " 43*0b57cec5SDimitry Andric "profile count if available."))); 44*0b57cec5SDimitry Andric 45*0b57cec5SDimitry Andric // Similar option above, but used to control BFI display only after MBP pass 46*0b57cec5SDimitry Andric cl::opt<GVDAGType> ViewBlockLayoutWithBFI( 47*0b57cec5SDimitry Andric "view-block-layout-with-bfi", cl::Hidden, 48*0b57cec5SDimitry Andric cl::desc( 49*0b57cec5SDimitry Andric "Pop up a window to show a dag displaying MBP layout and associated " 50*0b57cec5SDimitry Andric "block frequencies of the CFG."), 51*0b57cec5SDimitry Andric cl::values(clEnumValN(GVDT_None, "none", "do not display graphs."), 52*0b57cec5SDimitry Andric clEnumValN(GVDT_Fraction, "fraction", 53*0b57cec5SDimitry Andric "display a graph using the " 54*0b57cec5SDimitry Andric "fractional block frequency representation."), 55*0b57cec5SDimitry Andric clEnumValN(GVDT_Integer, "integer", 56*0b57cec5SDimitry Andric "display a graph using the raw " 57*0b57cec5SDimitry Andric "integer fractional block frequency representation."), 58*0b57cec5SDimitry Andric clEnumValN(GVDT_Count, "count", 59*0b57cec5SDimitry Andric "display a graph using the real " 60*0b57cec5SDimitry Andric "profile count if available."))); 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric // Command line option to specify the name of the function for CFG dump 63*0b57cec5SDimitry Andric // Defined in Analysis/BlockFrequencyInfo.cpp: -view-bfi-func-name= 64*0b57cec5SDimitry Andric extern cl::opt<std::string> ViewBlockFreqFuncName; 65*0b57cec5SDimitry Andric 66*0b57cec5SDimitry Andric // Command line option to specify hot frequency threshold. 67*0b57cec5SDimitry Andric // Defined in Analysis/BlockFrequencyInfo.cpp: -view-hot-freq-perc= 68*0b57cec5SDimitry Andric extern cl::opt<unsigned> ViewHotFreqPercent; 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric static cl::opt<bool> PrintMachineBlockFreq( 71*0b57cec5SDimitry Andric "print-machine-bfi", cl::init(false), cl::Hidden, 72*0b57cec5SDimitry Andric cl::desc("Print the machine block frequency info.")); 73*0b57cec5SDimitry Andric 74*0b57cec5SDimitry Andric // Command line option to specify the name of the function for block frequency 75*0b57cec5SDimitry Andric // dump. Defined in Analysis/BlockFrequencyInfo.cpp. 76*0b57cec5SDimitry Andric extern cl::opt<std::string> PrintBlockFreqFuncName; 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric static GVDAGType getGVDT() { 79*0b57cec5SDimitry Andric if (ViewBlockLayoutWithBFI != GVDT_None) 80*0b57cec5SDimitry Andric return ViewBlockLayoutWithBFI; 81*0b57cec5SDimitry Andric 82*0b57cec5SDimitry Andric return ViewMachineBlockFreqPropagationDAG; 83*0b57cec5SDimitry Andric } 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric namespace llvm { 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric template <> struct GraphTraits<MachineBlockFrequencyInfo *> { 88*0b57cec5SDimitry Andric using NodeRef = const MachineBasicBlock *; 89*0b57cec5SDimitry Andric using ChildIteratorType = MachineBasicBlock::const_succ_iterator; 90*0b57cec5SDimitry Andric using nodes_iterator = pointer_iterator<MachineFunction::const_iterator>; 91*0b57cec5SDimitry Andric 92*0b57cec5SDimitry Andric static NodeRef getEntryNode(const MachineBlockFrequencyInfo *G) { 93*0b57cec5SDimitry Andric return &G->getFunction()->front(); 94*0b57cec5SDimitry Andric } 95*0b57cec5SDimitry Andric 96*0b57cec5SDimitry Andric static ChildIteratorType child_begin(const NodeRef N) { 97*0b57cec5SDimitry Andric return N->succ_begin(); 98*0b57cec5SDimitry Andric } 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric static ChildIteratorType child_end(const NodeRef N) { return N->succ_end(); } 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric static nodes_iterator nodes_begin(const MachineBlockFrequencyInfo *G) { 103*0b57cec5SDimitry Andric return nodes_iterator(G->getFunction()->begin()); 104*0b57cec5SDimitry Andric } 105*0b57cec5SDimitry Andric 106*0b57cec5SDimitry Andric static nodes_iterator nodes_end(const MachineBlockFrequencyInfo *G) { 107*0b57cec5SDimitry Andric return nodes_iterator(G->getFunction()->end()); 108*0b57cec5SDimitry Andric } 109*0b57cec5SDimitry Andric }; 110*0b57cec5SDimitry Andric 111*0b57cec5SDimitry Andric using MBFIDOTGraphTraitsBase = 112*0b57cec5SDimitry Andric BFIDOTGraphTraitsBase<MachineBlockFrequencyInfo, 113*0b57cec5SDimitry Andric MachineBranchProbabilityInfo>; 114*0b57cec5SDimitry Andric 115*0b57cec5SDimitry Andric template <> 116*0b57cec5SDimitry Andric struct DOTGraphTraits<MachineBlockFrequencyInfo *> 117*0b57cec5SDimitry Andric : public MBFIDOTGraphTraitsBase { 118*0b57cec5SDimitry Andric const MachineFunction *CurFunc = nullptr; 119*0b57cec5SDimitry Andric DenseMap<const MachineBasicBlock *, int> LayoutOrderMap; 120*0b57cec5SDimitry Andric 121*0b57cec5SDimitry Andric explicit DOTGraphTraits(bool isSimple = false) 122*0b57cec5SDimitry Andric : MBFIDOTGraphTraitsBase(isSimple) {} 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric std::string getNodeLabel(const MachineBasicBlock *Node, 125*0b57cec5SDimitry Andric const MachineBlockFrequencyInfo *Graph) { 126*0b57cec5SDimitry Andric int layout_order = -1; 127*0b57cec5SDimitry Andric // Attach additional ordering information if 'isSimple' is false. 128*0b57cec5SDimitry Andric if (!isSimple()) { 129*0b57cec5SDimitry Andric const MachineFunction *F = Node->getParent(); 130*0b57cec5SDimitry Andric if (!CurFunc || F != CurFunc) { 131*0b57cec5SDimitry Andric if (CurFunc) 132*0b57cec5SDimitry Andric LayoutOrderMap.clear(); 133*0b57cec5SDimitry Andric 134*0b57cec5SDimitry Andric CurFunc = F; 135*0b57cec5SDimitry Andric int O = 0; 136*0b57cec5SDimitry Andric for (auto MBI = F->begin(); MBI != F->end(); ++MBI, ++O) { 137*0b57cec5SDimitry Andric LayoutOrderMap[&*MBI] = O; 138*0b57cec5SDimitry Andric } 139*0b57cec5SDimitry Andric } 140*0b57cec5SDimitry Andric layout_order = LayoutOrderMap[Node]; 141*0b57cec5SDimitry Andric } 142*0b57cec5SDimitry Andric return MBFIDOTGraphTraitsBase::getNodeLabel(Node, Graph, getGVDT(), 143*0b57cec5SDimitry Andric layout_order); 144*0b57cec5SDimitry Andric } 145*0b57cec5SDimitry Andric 146*0b57cec5SDimitry Andric std::string getNodeAttributes(const MachineBasicBlock *Node, 147*0b57cec5SDimitry Andric const MachineBlockFrequencyInfo *Graph) { 148*0b57cec5SDimitry Andric return MBFIDOTGraphTraitsBase::getNodeAttributes(Node, Graph, 149*0b57cec5SDimitry Andric ViewHotFreqPercent); 150*0b57cec5SDimitry Andric } 151*0b57cec5SDimitry Andric 152*0b57cec5SDimitry Andric std::string getEdgeAttributes(const MachineBasicBlock *Node, EdgeIter EI, 153*0b57cec5SDimitry Andric const MachineBlockFrequencyInfo *MBFI) { 154*0b57cec5SDimitry Andric return MBFIDOTGraphTraitsBase::getEdgeAttributes( 155*0b57cec5SDimitry Andric Node, EI, MBFI, MBFI->getMBPI(), ViewHotFreqPercent); 156*0b57cec5SDimitry Andric } 157*0b57cec5SDimitry Andric }; 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric } // end namespace llvm 160*0b57cec5SDimitry Andric 161*0b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(MachineBlockFrequencyInfo, DEBUG_TYPE, 162*0b57cec5SDimitry Andric "Machine Block Frequency Analysis", true, true) 163*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo) 164*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) 165*0b57cec5SDimitry Andric INITIALIZE_PASS_END(MachineBlockFrequencyInfo, DEBUG_TYPE, 166*0b57cec5SDimitry Andric "Machine Block Frequency Analysis", true, true) 167*0b57cec5SDimitry Andric 168*0b57cec5SDimitry Andric char MachineBlockFrequencyInfo::ID = 0; 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric MachineBlockFrequencyInfo::MachineBlockFrequencyInfo() 171*0b57cec5SDimitry Andric : MachineFunctionPass(ID) { 172*0b57cec5SDimitry Andric initializeMachineBlockFrequencyInfoPass(*PassRegistry::getPassRegistry()); 173*0b57cec5SDimitry Andric } 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric MachineBlockFrequencyInfo::~MachineBlockFrequencyInfo() = default; 176*0b57cec5SDimitry Andric 177*0b57cec5SDimitry Andric void MachineBlockFrequencyInfo::getAnalysisUsage(AnalysisUsage &AU) const { 178*0b57cec5SDimitry Andric AU.addRequired<MachineBranchProbabilityInfo>(); 179*0b57cec5SDimitry Andric AU.addRequired<MachineLoopInfo>(); 180*0b57cec5SDimitry Andric AU.setPreservesAll(); 181*0b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 182*0b57cec5SDimitry Andric } 183*0b57cec5SDimitry Andric 184*0b57cec5SDimitry Andric void MachineBlockFrequencyInfo::calculate( 185*0b57cec5SDimitry Andric const MachineFunction &F, const MachineBranchProbabilityInfo &MBPI, 186*0b57cec5SDimitry Andric const MachineLoopInfo &MLI) { 187*0b57cec5SDimitry Andric if (!MBFI) 188*0b57cec5SDimitry Andric MBFI.reset(new ImplType); 189*0b57cec5SDimitry Andric MBFI->calculate(F, MBPI, MLI); 190*0b57cec5SDimitry Andric if (ViewMachineBlockFreqPropagationDAG != GVDT_None && 191*0b57cec5SDimitry Andric (ViewBlockFreqFuncName.empty() || 192*0b57cec5SDimitry Andric F.getName().equals(ViewBlockFreqFuncName))) { 193*0b57cec5SDimitry Andric view("MachineBlockFrequencyDAGS." + F.getName()); 194*0b57cec5SDimitry Andric } 195*0b57cec5SDimitry Andric if (PrintMachineBlockFreq && 196*0b57cec5SDimitry Andric (PrintBlockFreqFuncName.empty() || 197*0b57cec5SDimitry Andric F.getName().equals(PrintBlockFreqFuncName))) { 198*0b57cec5SDimitry Andric MBFI->print(dbgs()); 199*0b57cec5SDimitry Andric } 200*0b57cec5SDimitry Andric } 201*0b57cec5SDimitry Andric 202*0b57cec5SDimitry Andric bool MachineBlockFrequencyInfo::runOnMachineFunction(MachineFunction &F) { 203*0b57cec5SDimitry Andric MachineBranchProbabilityInfo &MBPI = 204*0b57cec5SDimitry Andric getAnalysis<MachineBranchProbabilityInfo>(); 205*0b57cec5SDimitry Andric MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>(); 206*0b57cec5SDimitry Andric calculate(F, MBPI, MLI); 207*0b57cec5SDimitry Andric return false; 208*0b57cec5SDimitry Andric } 209*0b57cec5SDimitry Andric 210*0b57cec5SDimitry Andric void MachineBlockFrequencyInfo::releaseMemory() { MBFI.reset(); } 211*0b57cec5SDimitry Andric 212*0b57cec5SDimitry Andric /// Pop up a ghostview window with the current block frequency propagation 213*0b57cec5SDimitry Andric /// rendered using dot. 214*0b57cec5SDimitry Andric void MachineBlockFrequencyInfo::view(const Twine &Name, bool isSimple) const { 215*0b57cec5SDimitry Andric // This code is only for debugging. 216*0b57cec5SDimitry Andric ViewGraph(const_cast<MachineBlockFrequencyInfo *>(this), Name, isSimple); 217*0b57cec5SDimitry Andric } 218*0b57cec5SDimitry Andric 219*0b57cec5SDimitry Andric BlockFrequency 220*0b57cec5SDimitry Andric MachineBlockFrequencyInfo::getBlockFreq(const MachineBasicBlock *MBB) const { 221*0b57cec5SDimitry Andric return MBFI ? MBFI->getBlockFreq(MBB) : 0; 222*0b57cec5SDimitry Andric } 223*0b57cec5SDimitry Andric 224*0b57cec5SDimitry Andric Optional<uint64_t> MachineBlockFrequencyInfo::getBlockProfileCount( 225*0b57cec5SDimitry Andric const MachineBasicBlock *MBB) const { 226*0b57cec5SDimitry Andric const Function &F = MBFI->getFunction()->getFunction(); 227*0b57cec5SDimitry Andric return MBFI ? MBFI->getBlockProfileCount(F, MBB) : None; 228*0b57cec5SDimitry Andric } 229*0b57cec5SDimitry Andric 230*0b57cec5SDimitry Andric Optional<uint64_t> 231*0b57cec5SDimitry Andric MachineBlockFrequencyInfo::getProfileCountFromFreq(uint64_t Freq) const { 232*0b57cec5SDimitry Andric const Function &F = MBFI->getFunction()->getFunction(); 233*0b57cec5SDimitry Andric return MBFI ? MBFI->getProfileCountFromFreq(F, Freq) : None; 234*0b57cec5SDimitry Andric } 235*0b57cec5SDimitry Andric 236*0b57cec5SDimitry Andric bool 237*0b57cec5SDimitry Andric MachineBlockFrequencyInfo::isIrrLoopHeader(const MachineBasicBlock *MBB) { 238*0b57cec5SDimitry Andric assert(MBFI && "Expected analysis to be available"); 239*0b57cec5SDimitry Andric return MBFI->isIrrLoopHeader(MBB); 240*0b57cec5SDimitry Andric } 241*0b57cec5SDimitry Andric 242*0b57cec5SDimitry Andric const MachineFunction *MachineBlockFrequencyInfo::getFunction() const { 243*0b57cec5SDimitry Andric return MBFI ? MBFI->getFunction() : nullptr; 244*0b57cec5SDimitry Andric } 245*0b57cec5SDimitry Andric 246*0b57cec5SDimitry Andric const MachineBranchProbabilityInfo *MachineBlockFrequencyInfo::getMBPI() const { 247*0b57cec5SDimitry Andric return MBFI ? &MBFI->getBPI() : nullptr; 248*0b57cec5SDimitry Andric } 249*0b57cec5SDimitry Andric 250*0b57cec5SDimitry Andric raw_ostream & 251*0b57cec5SDimitry Andric MachineBlockFrequencyInfo::printBlockFreq(raw_ostream &OS, 252*0b57cec5SDimitry Andric const BlockFrequency Freq) const { 253*0b57cec5SDimitry Andric return MBFI ? MBFI->printBlockFreq(OS, Freq) : OS; 254*0b57cec5SDimitry Andric } 255*0b57cec5SDimitry Andric 256*0b57cec5SDimitry Andric raw_ostream & 257*0b57cec5SDimitry Andric MachineBlockFrequencyInfo::printBlockFreq(raw_ostream &OS, 258*0b57cec5SDimitry Andric const MachineBasicBlock *MBB) const { 259*0b57cec5SDimitry Andric return MBFI ? MBFI->printBlockFreq(OS, MBB) : OS; 260*0b57cec5SDimitry Andric } 261*0b57cec5SDimitry Andric 262*0b57cec5SDimitry Andric uint64_t MachineBlockFrequencyInfo::getEntryFreq() const { 263*0b57cec5SDimitry Andric return MBFI ? MBFI->getEntryFreq() : 0; 264*0b57cec5SDimitry Andric } 265