xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/MachineBlockFrequencyInfo.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric //===- MachineBlockFrequencyInfo.cpp - MBB Frequency Analysis -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Loops should be simplified before this analysis.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
140b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
150b57cec5SDimitry Andric #include "llvm/ADT/None.h"
160b57cec5SDimitry Andric #include "llvm/ADT/iterator.h"
170b57cec5SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
22480093f4SDimitry Andric #include "llvm/InitializePasses.h"
230b57cec5SDimitry Andric #include "llvm/Pass.h"
240b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
250b57cec5SDimitry Andric #include "llvm/Support/GraphWriter.h"
260b57cec5SDimitry Andric #include <string>
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric using namespace llvm;
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric #define DEBUG_TYPE "machine-block-freq"
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric static cl::opt<GVDAGType> ViewMachineBlockFreqPropagationDAG(
330b57cec5SDimitry Andric     "view-machine-block-freq-propagation-dags", cl::Hidden,
340b57cec5SDimitry Andric     cl::desc("Pop up a window to show a dag displaying how machine block "
350b57cec5SDimitry Andric              "frequencies propagate through the CFG."),
360b57cec5SDimitry Andric     cl::values(clEnumValN(GVDT_None, "none", "do not display graphs."),
370b57cec5SDimitry Andric                clEnumValN(GVDT_Fraction, "fraction",
380b57cec5SDimitry Andric                           "display a graph using the "
390b57cec5SDimitry Andric                           "fractional block frequency representation."),
400b57cec5SDimitry Andric                clEnumValN(GVDT_Integer, "integer",
410b57cec5SDimitry Andric                           "display a graph using the raw "
420b57cec5SDimitry Andric                           "integer fractional block frequency representation."),
430b57cec5SDimitry Andric                clEnumValN(GVDT_Count, "count", "display a graph using the real "
440b57cec5SDimitry Andric                                                "profile count if available.")));
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric // Similar option above, but used to control BFI display only after MBP pass
470b57cec5SDimitry Andric cl::opt<GVDAGType> ViewBlockLayoutWithBFI(
480b57cec5SDimitry Andric     "view-block-layout-with-bfi", cl::Hidden,
490b57cec5SDimitry Andric     cl::desc(
500b57cec5SDimitry Andric         "Pop up a window to show a dag displaying MBP layout and associated "
510b57cec5SDimitry Andric         "block frequencies of the CFG."),
520b57cec5SDimitry Andric     cl::values(clEnumValN(GVDT_None, "none", "do not display graphs."),
530b57cec5SDimitry Andric                clEnumValN(GVDT_Fraction, "fraction",
540b57cec5SDimitry Andric                           "display a graph using the "
550b57cec5SDimitry Andric                           "fractional block frequency representation."),
560b57cec5SDimitry Andric                clEnumValN(GVDT_Integer, "integer",
570b57cec5SDimitry Andric                           "display a graph using the raw "
580b57cec5SDimitry Andric                           "integer fractional block frequency representation."),
590b57cec5SDimitry Andric                clEnumValN(GVDT_Count, "count",
600b57cec5SDimitry Andric                           "display a graph using the real "
610b57cec5SDimitry Andric                           "profile count if available.")));
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric // Command line option to specify the name of the function for CFG dump
640b57cec5SDimitry Andric // Defined in Analysis/BlockFrequencyInfo.cpp:  -view-bfi-func-name=
650b57cec5SDimitry Andric extern cl::opt<std::string> ViewBlockFreqFuncName;
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric // Command line option to specify hot frequency threshold.
680b57cec5SDimitry Andric // Defined in Analysis/BlockFrequencyInfo.cpp:  -view-hot-freq-perc=
690b57cec5SDimitry Andric extern cl::opt<unsigned> ViewHotFreqPercent;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric static cl::opt<bool> PrintMachineBlockFreq(
720b57cec5SDimitry Andric     "print-machine-bfi", cl::init(false), cl::Hidden,
730b57cec5SDimitry Andric     cl::desc("Print the machine block frequency info."));
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric // Command line option to specify the name of the function for block frequency
760b57cec5SDimitry Andric // dump. Defined in Analysis/BlockFrequencyInfo.cpp.
770b57cec5SDimitry Andric extern cl::opt<std::string> PrintBlockFreqFuncName;
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric static GVDAGType getGVDT() {
800b57cec5SDimitry Andric   if (ViewBlockLayoutWithBFI != GVDT_None)
810b57cec5SDimitry Andric     return ViewBlockLayoutWithBFI;
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   return ViewMachineBlockFreqPropagationDAG;
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric namespace llvm {
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric template <> struct GraphTraits<MachineBlockFrequencyInfo *> {
890b57cec5SDimitry Andric   using NodeRef = const MachineBasicBlock *;
900b57cec5SDimitry Andric   using ChildIteratorType = MachineBasicBlock::const_succ_iterator;
910b57cec5SDimitry Andric   using nodes_iterator = pointer_iterator<MachineFunction::const_iterator>;
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   static NodeRef getEntryNode(const MachineBlockFrequencyInfo *G) {
940b57cec5SDimitry Andric     return &G->getFunction()->front();
950b57cec5SDimitry Andric   }
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   static ChildIteratorType child_begin(const NodeRef N) {
980b57cec5SDimitry Andric     return N->succ_begin();
990b57cec5SDimitry Andric   }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   static ChildIteratorType child_end(const NodeRef N) { return N->succ_end(); }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   static nodes_iterator nodes_begin(const MachineBlockFrequencyInfo *G) {
1040b57cec5SDimitry Andric     return nodes_iterator(G->getFunction()->begin());
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   static nodes_iterator nodes_end(const MachineBlockFrequencyInfo *G) {
1080b57cec5SDimitry Andric     return nodes_iterator(G->getFunction()->end());
1090b57cec5SDimitry Andric   }
1100b57cec5SDimitry Andric };
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric using MBFIDOTGraphTraitsBase =
1130b57cec5SDimitry Andric     BFIDOTGraphTraitsBase<MachineBlockFrequencyInfo,
1140b57cec5SDimitry Andric                           MachineBranchProbabilityInfo>;
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric template <>
1170b57cec5SDimitry Andric struct DOTGraphTraits<MachineBlockFrequencyInfo *>
1180b57cec5SDimitry Andric     : public MBFIDOTGraphTraitsBase {
1190b57cec5SDimitry Andric   const MachineFunction *CurFunc = nullptr;
1200b57cec5SDimitry Andric   DenseMap<const MachineBasicBlock *, int> LayoutOrderMap;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   explicit DOTGraphTraits(bool isSimple = false)
1230b57cec5SDimitry Andric       : MBFIDOTGraphTraitsBase(isSimple) {}
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   std::string getNodeLabel(const MachineBasicBlock *Node,
1260b57cec5SDimitry Andric                            const MachineBlockFrequencyInfo *Graph) {
1270b57cec5SDimitry Andric     int layout_order = -1;
1280b57cec5SDimitry Andric     // Attach additional ordering information if 'isSimple' is false.
1290b57cec5SDimitry Andric     if (!isSimple()) {
1300b57cec5SDimitry Andric       const MachineFunction *F = Node->getParent();
1310b57cec5SDimitry Andric       if (!CurFunc || F != CurFunc) {
1320b57cec5SDimitry Andric         if (CurFunc)
1330b57cec5SDimitry Andric           LayoutOrderMap.clear();
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric         CurFunc = F;
1360b57cec5SDimitry Andric         int O = 0;
1370b57cec5SDimitry Andric         for (auto MBI = F->begin(); MBI != F->end(); ++MBI, ++O) {
1380b57cec5SDimitry Andric           LayoutOrderMap[&*MBI] = O;
1390b57cec5SDimitry Andric         }
1400b57cec5SDimitry Andric       }
1410b57cec5SDimitry Andric       layout_order = LayoutOrderMap[Node];
1420b57cec5SDimitry Andric     }
1430b57cec5SDimitry Andric     return MBFIDOTGraphTraitsBase::getNodeLabel(Node, Graph, getGVDT(),
1440b57cec5SDimitry Andric                                                 layout_order);
1450b57cec5SDimitry Andric   }
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   std::string getNodeAttributes(const MachineBasicBlock *Node,
1480b57cec5SDimitry Andric                                 const MachineBlockFrequencyInfo *Graph) {
1490b57cec5SDimitry Andric     return MBFIDOTGraphTraitsBase::getNodeAttributes(Node, Graph,
1500b57cec5SDimitry Andric                                                      ViewHotFreqPercent);
1510b57cec5SDimitry Andric   }
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   std::string getEdgeAttributes(const MachineBasicBlock *Node, EdgeIter EI,
1540b57cec5SDimitry Andric                                 const MachineBlockFrequencyInfo *MBFI) {
1550b57cec5SDimitry Andric     return MBFIDOTGraphTraitsBase::getEdgeAttributes(
1560b57cec5SDimitry Andric         Node, EI, MBFI, MBFI->getMBPI(), ViewHotFreqPercent);
1570b57cec5SDimitry Andric   }
1580b57cec5SDimitry Andric };
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric } // end namespace llvm
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(MachineBlockFrequencyInfo, DEBUG_TYPE,
1630b57cec5SDimitry Andric                       "Machine Block Frequency Analysis", true, true)
1640b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
1650b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
1660b57cec5SDimitry Andric INITIALIZE_PASS_END(MachineBlockFrequencyInfo, DEBUG_TYPE,
1670b57cec5SDimitry Andric                     "Machine Block Frequency Analysis", true, true)
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric char MachineBlockFrequencyInfo::ID = 0;
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric MachineBlockFrequencyInfo::MachineBlockFrequencyInfo()
1720b57cec5SDimitry Andric     : MachineFunctionPass(ID) {
1730b57cec5SDimitry Andric   initializeMachineBlockFrequencyInfoPass(*PassRegistry::getPassRegistry());
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric 
176480093f4SDimitry Andric MachineBlockFrequencyInfo::MachineBlockFrequencyInfo(
177480093f4SDimitry Andric       MachineFunction &F,
178480093f4SDimitry Andric       MachineBranchProbabilityInfo &MBPI,
179480093f4SDimitry Andric       MachineLoopInfo &MLI) : MachineFunctionPass(ID) {
180480093f4SDimitry Andric   calculate(F, MBPI, MLI);
181480093f4SDimitry Andric }
182480093f4SDimitry Andric 
1830b57cec5SDimitry Andric MachineBlockFrequencyInfo::~MachineBlockFrequencyInfo() = default;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric void MachineBlockFrequencyInfo::getAnalysisUsage(AnalysisUsage &AU) const {
1860b57cec5SDimitry Andric   AU.addRequired<MachineBranchProbabilityInfo>();
1870b57cec5SDimitry Andric   AU.addRequired<MachineLoopInfo>();
1880b57cec5SDimitry Andric   AU.setPreservesAll();
1890b57cec5SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric void MachineBlockFrequencyInfo::calculate(
1930b57cec5SDimitry Andric     const MachineFunction &F, const MachineBranchProbabilityInfo &MBPI,
1940b57cec5SDimitry Andric     const MachineLoopInfo &MLI) {
1950b57cec5SDimitry Andric   if (!MBFI)
1960b57cec5SDimitry Andric     MBFI.reset(new ImplType);
1970b57cec5SDimitry Andric   MBFI->calculate(F, MBPI, MLI);
1980b57cec5SDimitry Andric   if (ViewMachineBlockFreqPropagationDAG != GVDT_None &&
1990b57cec5SDimitry Andric       (ViewBlockFreqFuncName.empty() ||
2000b57cec5SDimitry Andric        F.getName().equals(ViewBlockFreqFuncName))) {
2010b57cec5SDimitry Andric     view("MachineBlockFrequencyDAGS." + F.getName());
2020b57cec5SDimitry Andric   }
2030b57cec5SDimitry Andric   if (PrintMachineBlockFreq &&
2040b57cec5SDimitry Andric       (PrintBlockFreqFuncName.empty() ||
2050b57cec5SDimitry Andric        F.getName().equals(PrintBlockFreqFuncName))) {
2060b57cec5SDimitry Andric     MBFI->print(dbgs());
2070b57cec5SDimitry Andric   }
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric bool MachineBlockFrequencyInfo::runOnMachineFunction(MachineFunction &F) {
2110b57cec5SDimitry Andric   MachineBranchProbabilityInfo &MBPI =
2120b57cec5SDimitry Andric       getAnalysis<MachineBranchProbabilityInfo>();
2130b57cec5SDimitry Andric   MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
2140b57cec5SDimitry Andric   calculate(F, MBPI, MLI);
2150b57cec5SDimitry Andric   return false;
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric void MachineBlockFrequencyInfo::releaseMemory() { MBFI.reset(); }
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric /// Pop up a ghostview window with the current block frequency propagation
2210b57cec5SDimitry Andric /// rendered using dot.
2220b57cec5SDimitry Andric void MachineBlockFrequencyInfo::view(const Twine &Name, bool isSimple) const {
2230b57cec5SDimitry Andric   // This code is only for debugging.
2240b57cec5SDimitry Andric   ViewGraph(const_cast<MachineBlockFrequencyInfo *>(this), Name, isSimple);
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric BlockFrequency
2280b57cec5SDimitry Andric MachineBlockFrequencyInfo::getBlockFreq(const MachineBasicBlock *MBB) const {
2290b57cec5SDimitry Andric   return MBFI ? MBFI->getBlockFreq(MBB) : 0;
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric Optional<uint64_t> MachineBlockFrequencyInfo::getBlockProfileCount(
2330b57cec5SDimitry Andric     const MachineBasicBlock *MBB) const {
2340b57cec5SDimitry Andric   const Function &F = MBFI->getFunction()->getFunction();
2350b57cec5SDimitry Andric   return MBFI ? MBFI->getBlockProfileCount(F, MBB) : None;
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric Optional<uint64_t>
2390b57cec5SDimitry Andric MachineBlockFrequencyInfo::getProfileCountFromFreq(uint64_t Freq) const {
2400b57cec5SDimitry Andric   const Function &F = MBFI->getFunction()->getFunction();
2410b57cec5SDimitry Andric   return MBFI ? MBFI->getProfileCountFromFreq(F, Freq) : None;
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric bool
2450b57cec5SDimitry Andric MachineBlockFrequencyInfo::isIrrLoopHeader(const MachineBasicBlock *MBB) {
2460b57cec5SDimitry Andric   assert(MBFI && "Expected analysis to be available");
2470b57cec5SDimitry Andric   return MBFI->isIrrLoopHeader(MBB);
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric 
250*5ffd83dbSDimitry Andric void MachineBlockFrequencyInfo::setBlockFreq(const MachineBasicBlock *MBB,
251*5ffd83dbSDimitry Andric                                              uint64_t Freq) {
252*5ffd83dbSDimitry Andric   assert(MBFI && "Expected analysis to be available");
253*5ffd83dbSDimitry Andric   MBFI->setBlockFreq(MBB, Freq);
254*5ffd83dbSDimitry Andric }
255*5ffd83dbSDimitry Andric 
2560b57cec5SDimitry Andric const MachineFunction *MachineBlockFrequencyInfo::getFunction() const {
2570b57cec5SDimitry Andric   return MBFI ? MBFI->getFunction() : nullptr;
2580b57cec5SDimitry Andric }
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric const MachineBranchProbabilityInfo *MachineBlockFrequencyInfo::getMBPI() const {
2610b57cec5SDimitry Andric   return MBFI ? &MBFI->getBPI() : nullptr;
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric raw_ostream &
2650b57cec5SDimitry Andric MachineBlockFrequencyInfo::printBlockFreq(raw_ostream &OS,
2660b57cec5SDimitry Andric                                           const BlockFrequency Freq) const {
2670b57cec5SDimitry Andric   return MBFI ? MBFI->printBlockFreq(OS, Freq) : OS;
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric raw_ostream &
2710b57cec5SDimitry Andric MachineBlockFrequencyInfo::printBlockFreq(raw_ostream &OS,
2720b57cec5SDimitry Andric                                           const MachineBasicBlock *MBB) const {
2730b57cec5SDimitry Andric   return MBFI ? MBFI->printBlockFreq(OS, MBB) : OS;
2740b57cec5SDimitry Andric }
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric uint64_t MachineBlockFrequencyInfo::getEntryFreq() const {
2770b57cec5SDimitry Andric   return MBFI ? MBFI->getEntryFreq() : 0;
2780b57cec5SDimitry Andric }
279