106f32e7eSjoerg //===- MachineBlockFrequencyInfo.cpp - MBB Frequency Analysis -------------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // Loops should be simplified before this analysis.
1006f32e7eSjoerg //
1106f32e7eSjoerg //===----------------------------------------------------------------------===//
1206f32e7eSjoerg 
1306f32e7eSjoerg #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
1406f32e7eSjoerg #include "llvm/ADT/DenseMap.h"
1506f32e7eSjoerg #include "llvm/ADT/None.h"
1606f32e7eSjoerg #include "llvm/ADT/iterator.h"
1706f32e7eSjoerg #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
1806f32e7eSjoerg #include "llvm/CodeGen/MachineBasicBlock.h"
1906f32e7eSjoerg #include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
2006f32e7eSjoerg #include "llvm/CodeGen/MachineFunction.h"
2106f32e7eSjoerg #include "llvm/CodeGen/MachineLoopInfo.h"
22*da58b97aSjoerg #include "llvm/InitializePasses.h"
2306f32e7eSjoerg #include "llvm/Pass.h"
2406f32e7eSjoerg #include "llvm/Support/CommandLine.h"
2506f32e7eSjoerg #include "llvm/Support/GraphWriter.h"
2606f32e7eSjoerg #include <string>
2706f32e7eSjoerg 
2806f32e7eSjoerg using namespace llvm;
2906f32e7eSjoerg 
3006f32e7eSjoerg #define DEBUG_TYPE "machine-block-freq"
3106f32e7eSjoerg 
32*da58b97aSjoerg namespace llvm {
3306f32e7eSjoerg static cl::opt<GVDAGType> ViewMachineBlockFreqPropagationDAG(
3406f32e7eSjoerg     "view-machine-block-freq-propagation-dags", cl::Hidden,
3506f32e7eSjoerg     cl::desc("Pop up a window to show a dag displaying how machine block "
3606f32e7eSjoerg              "frequencies propagate through the CFG."),
3706f32e7eSjoerg     cl::values(clEnumValN(GVDT_None, "none", "do not display graphs."),
3806f32e7eSjoerg                clEnumValN(GVDT_Fraction, "fraction",
3906f32e7eSjoerg                           "display a graph using the "
4006f32e7eSjoerg                           "fractional block frequency representation."),
4106f32e7eSjoerg                clEnumValN(GVDT_Integer, "integer",
4206f32e7eSjoerg                           "display a graph using the raw "
4306f32e7eSjoerg                           "integer fractional block frequency representation."),
4406f32e7eSjoerg                clEnumValN(GVDT_Count, "count", "display a graph using the real "
4506f32e7eSjoerg                                                "profile count if available.")));
4606f32e7eSjoerg 
4706f32e7eSjoerg // Similar option above, but used to control BFI display only after MBP pass
4806f32e7eSjoerg cl::opt<GVDAGType> ViewBlockLayoutWithBFI(
4906f32e7eSjoerg     "view-block-layout-with-bfi", cl::Hidden,
5006f32e7eSjoerg     cl::desc(
5106f32e7eSjoerg         "Pop up a window to show a dag displaying MBP layout and associated "
5206f32e7eSjoerg         "block frequencies of the CFG."),
5306f32e7eSjoerg     cl::values(clEnumValN(GVDT_None, "none", "do not display graphs."),
5406f32e7eSjoerg                clEnumValN(GVDT_Fraction, "fraction",
5506f32e7eSjoerg                           "display a graph using the "
5606f32e7eSjoerg                           "fractional block frequency representation."),
5706f32e7eSjoerg                clEnumValN(GVDT_Integer, "integer",
5806f32e7eSjoerg                           "display a graph using the raw "
5906f32e7eSjoerg                           "integer fractional block frequency representation."),
6006f32e7eSjoerg                clEnumValN(GVDT_Count, "count",
6106f32e7eSjoerg                           "display a graph using the real "
6206f32e7eSjoerg                           "profile count if available.")));
6306f32e7eSjoerg 
6406f32e7eSjoerg // Command line option to specify the name of the function for CFG dump
6506f32e7eSjoerg // Defined in Analysis/BlockFrequencyInfo.cpp:  -view-bfi-func-name=
6606f32e7eSjoerg extern cl::opt<std::string> ViewBlockFreqFuncName;
6706f32e7eSjoerg 
6806f32e7eSjoerg // Command line option to specify hot frequency threshold.
6906f32e7eSjoerg // Defined in Analysis/BlockFrequencyInfo.cpp:  -view-hot-freq-perc=
7006f32e7eSjoerg extern cl::opt<unsigned> ViewHotFreqPercent;
7106f32e7eSjoerg 
7206f32e7eSjoerg static cl::opt<bool> PrintMachineBlockFreq(
7306f32e7eSjoerg     "print-machine-bfi", cl::init(false), cl::Hidden,
7406f32e7eSjoerg     cl::desc("Print the machine block frequency info."));
7506f32e7eSjoerg 
7606f32e7eSjoerg // Command line option to specify the name of the function for block frequency
7706f32e7eSjoerg // dump. Defined in Analysis/BlockFrequencyInfo.cpp.
7806f32e7eSjoerg extern cl::opt<std::string> PrintBlockFreqFuncName;
79*da58b97aSjoerg } // namespace llvm
8006f32e7eSjoerg 
getGVDT()8106f32e7eSjoerg static GVDAGType getGVDT() {
8206f32e7eSjoerg   if (ViewBlockLayoutWithBFI != GVDT_None)
8306f32e7eSjoerg     return ViewBlockLayoutWithBFI;
8406f32e7eSjoerg 
8506f32e7eSjoerg   return ViewMachineBlockFreqPropagationDAG;
8606f32e7eSjoerg }
8706f32e7eSjoerg 
8806f32e7eSjoerg namespace llvm {
8906f32e7eSjoerg 
9006f32e7eSjoerg template <> struct GraphTraits<MachineBlockFrequencyInfo *> {
9106f32e7eSjoerg   using NodeRef = const MachineBasicBlock *;
9206f32e7eSjoerg   using ChildIteratorType = MachineBasicBlock::const_succ_iterator;
9306f32e7eSjoerg   using nodes_iterator = pointer_iterator<MachineFunction::const_iterator>;
9406f32e7eSjoerg 
getEntryNodellvm::GraphTraits9506f32e7eSjoerg   static NodeRef getEntryNode(const MachineBlockFrequencyInfo *G) {
9606f32e7eSjoerg     return &G->getFunction()->front();
9706f32e7eSjoerg   }
9806f32e7eSjoerg 
child_beginllvm::GraphTraits9906f32e7eSjoerg   static ChildIteratorType child_begin(const NodeRef N) {
10006f32e7eSjoerg     return N->succ_begin();
10106f32e7eSjoerg   }
10206f32e7eSjoerg 
child_endllvm::GraphTraits10306f32e7eSjoerg   static ChildIteratorType child_end(const NodeRef N) { return N->succ_end(); }
10406f32e7eSjoerg 
nodes_beginllvm::GraphTraits10506f32e7eSjoerg   static nodes_iterator nodes_begin(const MachineBlockFrequencyInfo *G) {
10606f32e7eSjoerg     return nodes_iterator(G->getFunction()->begin());
10706f32e7eSjoerg   }
10806f32e7eSjoerg 
nodes_endllvm::GraphTraits10906f32e7eSjoerg   static nodes_iterator nodes_end(const MachineBlockFrequencyInfo *G) {
11006f32e7eSjoerg     return nodes_iterator(G->getFunction()->end());
11106f32e7eSjoerg   }
11206f32e7eSjoerg };
11306f32e7eSjoerg 
11406f32e7eSjoerg using MBFIDOTGraphTraitsBase =
11506f32e7eSjoerg     BFIDOTGraphTraitsBase<MachineBlockFrequencyInfo,
11606f32e7eSjoerg                           MachineBranchProbabilityInfo>;
11706f32e7eSjoerg 
11806f32e7eSjoerg template <>
11906f32e7eSjoerg struct DOTGraphTraits<MachineBlockFrequencyInfo *>
12006f32e7eSjoerg     : public MBFIDOTGraphTraitsBase {
12106f32e7eSjoerg   const MachineFunction *CurFunc = nullptr;
12206f32e7eSjoerg   DenseMap<const MachineBasicBlock *, int> LayoutOrderMap;
12306f32e7eSjoerg 
DOTGraphTraitsllvm::DOTGraphTraits12406f32e7eSjoerg   explicit DOTGraphTraits(bool isSimple = false)
12506f32e7eSjoerg       : MBFIDOTGraphTraitsBase(isSimple) {}
12606f32e7eSjoerg 
getNodeLabelllvm::DOTGraphTraits12706f32e7eSjoerg   std::string getNodeLabel(const MachineBasicBlock *Node,
12806f32e7eSjoerg                            const MachineBlockFrequencyInfo *Graph) {
12906f32e7eSjoerg     int layout_order = -1;
13006f32e7eSjoerg     // Attach additional ordering information if 'isSimple' is false.
13106f32e7eSjoerg     if (!isSimple()) {
13206f32e7eSjoerg       const MachineFunction *F = Node->getParent();
13306f32e7eSjoerg       if (!CurFunc || F != CurFunc) {
13406f32e7eSjoerg         if (CurFunc)
13506f32e7eSjoerg           LayoutOrderMap.clear();
13606f32e7eSjoerg 
13706f32e7eSjoerg         CurFunc = F;
13806f32e7eSjoerg         int O = 0;
13906f32e7eSjoerg         for (auto MBI = F->begin(); MBI != F->end(); ++MBI, ++O) {
14006f32e7eSjoerg           LayoutOrderMap[&*MBI] = O;
14106f32e7eSjoerg         }
14206f32e7eSjoerg       }
14306f32e7eSjoerg       layout_order = LayoutOrderMap[Node];
14406f32e7eSjoerg     }
14506f32e7eSjoerg     return MBFIDOTGraphTraitsBase::getNodeLabel(Node, Graph, getGVDT(),
14606f32e7eSjoerg                                                 layout_order);
14706f32e7eSjoerg   }
14806f32e7eSjoerg 
getNodeAttributesllvm::DOTGraphTraits14906f32e7eSjoerg   std::string getNodeAttributes(const MachineBasicBlock *Node,
15006f32e7eSjoerg                                 const MachineBlockFrequencyInfo *Graph) {
15106f32e7eSjoerg     return MBFIDOTGraphTraitsBase::getNodeAttributes(Node, Graph,
15206f32e7eSjoerg                                                      ViewHotFreqPercent);
15306f32e7eSjoerg   }
15406f32e7eSjoerg 
getEdgeAttributesllvm::DOTGraphTraits15506f32e7eSjoerg   std::string getEdgeAttributes(const MachineBasicBlock *Node, EdgeIter EI,
15606f32e7eSjoerg                                 const MachineBlockFrequencyInfo *MBFI) {
15706f32e7eSjoerg     return MBFIDOTGraphTraitsBase::getEdgeAttributes(
15806f32e7eSjoerg         Node, EI, MBFI, MBFI->getMBPI(), ViewHotFreqPercent);
15906f32e7eSjoerg   }
16006f32e7eSjoerg };
16106f32e7eSjoerg 
16206f32e7eSjoerg } // end namespace llvm
16306f32e7eSjoerg 
16406f32e7eSjoerg INITIALIZE_PASS_BEGIN(MachineBlockFrequencyInfo, DEBUG_TYPE,
16506f32e7eSjoerg                       "Machine Block Frequency Analysis", true, true)
16606f32e7eSjoerg INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
16706f32e7eSjoerg INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
16806f32e7eSjoerg INITIALIZE_PASS_END(MachineBlockFrequencyInfo, DEBUG_TYPE,
16906f32e7eSjoerg                     "Machine Block Frequency Analysis", true, true)
17006f32e7eSjoerg 
17106f32e7eSjoerg char MachineBlockFrequencyInfo::ID = 0;
17206f32e7eSjoerg 
MachineBlockFrequencyInfo()17306f32e7eSjoerg MachineBlockFrequencyInfo::MachineBlockFrequencyInfo()
17406f32e7eSjoerg     : MachineFunctionPass(ID) {
17506f32e7eSjoerg   initializeMachineBlockFrequencyInfoPass(*PassRegistry::getPassRegistry());
17606f32e7eSjoerg }
17706f32e7eSjoerg 
MachineBlockFrequencyInfo(MachineFunction & F,MachineBranchProbabilityInfo & MBPI,MachineLoopInfo & MLI)17806f32e7eSjoerg MachineBlockFrequencyInfo::MachineBlockFrequencyInfo(
17906f32e7eSjoerg       MachineFunction &F,
18006f32e7eSjoerg       MachineBranchProbabilityInfo &MBPI,
18106f32e7eSjoerg       MachineLoopInfo &MLI) : MachineFunctionPass(ID) {
18206f32e7eSjoerg   calculate(F, MBPI, MLI);
18306f32e7eSjoerg }
18406f32e7eSjoerg 
18506f32e7eSjoerg MachineBlockFrequencyInfo::~MachineBlockFrequencyInfo() = default;
18606f32e7eSjoerg 
getAnalysisUsage(AnalysisUsage & AU) const18706f32e7eSjoerg void MachineBlockFrequencyInfo::getAnalysisUsage(AnalysisUsage &AU) const {
18806f32e7eSjoerg   AU.addRequired<MachineBranchProbabilityInfo>();
18906f32e7eSjoerg   AU.addRequired<MachineLoopInfo>();
19006f32e7eSjoerg   AU.setPreservesAll();
19106f32e7eSjoerg   MachineFunctionPass::getAnalysisUsage(AU);
19206f32e7eSjoerg }
19306f32e7eSjoerg 
calculate(const MachineFunction & F,const MachineBranchProbabilityInfo & MBPI,const MachineLoopInfo & MLI)19406f32e7eSjoerg void MachineBlockFrequencyInfo::calculate(
19506f32e7eSjoerg     const MachineFunction &F, const MachineBranchProbabilityInfo &MBPI,
19606f32e7eSjoerg     const MachineLoopInfo &MLI) {
19706f32e7eSjoerg   if (!MBFI)
19806f32e7eSjoerg     MBFI.reset(new ImplType);
19906f32e7eSjoerg   MBFI->calculate(F, MBPI, MLI);
20006f32e7eSjoerg   if (ViewMachineBlockFreqPropagationDAG != GVDT_None &&
20106f32e7eSjoerg       (ViewBlockFreqFuncName.empty() ||
20206f32e7eSjoerg        F.getName().equals(ViewBlockFreqFuncName))) {
20306f32e7eSjoerg     view("MachineBlockFrequencyDAGS." + F.getName());
20406f32e7eSjoerg   }
20506f32e7eSjoerg   if (PrintMachineBlockFreq &&
20606f32e7eSjoerg       (PrintBlockFreqFuncName.empty() ||
20706f32e7eSjoerg        F.getName().equals(PrintBlockFreqFuncName))) {
20806f32e7eSjoerg     MBFI->print(dbgs());
20906f32e7eSjoerg   }
21006f32e7eSjoerg }
21106f32e7eSjoerg 
runOnMachineFunction(MachineFunction & F)21206f32e7eSjoerg bool MachineBlockFrequencyInfo::runOnMachineFunction(MachineFunction &F) {
21306f32e7eSjoerg   MachineBranchProbabilityInfo &MBPI =
21406f32e7eSjoerg       getAnalysis<MachineBranchProbabilityInfo>();
21506f32e7eSjoerg   MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
21606f32e7eSjoerg   calculate(F, MBPI, MLI);
21706f32e7eSjoerg   return false;
21806f32e7eSjoerg }
21906f32e7eSjoerg 
releaseMemory()22006f32e7eSjoerg void MachineBlockFrequencyInfo::releaseMemory() { MBFI.reset(); }
22106f32e7eSjoerg 
22206f32e7eSjoerg /// Pop up a ghostview window with the current block frequency propagation
22306f32e7eSjoerg /// rendered using dot.
view(const Twine & Name,bool isSimple) const22406f32e7eSjoerg void MachineBlockFrequencyInfo::view(const Twine &Name, bool isSimple) const {
22506f32e7eSjoerg   // This code is only for debugging.
22606f32e7eSjoerg   ViewGraph(const_cast<MachineBlockFrequencyInfo *>(this), Name, isSimple);
22706f32e7eSjoerg }
22806f32e7eSjoerg 
22906f32e7eSjoerg BlockFrequency
getBlockFreq(const MachineBasicBlock * MBB) const23006f32e7eSjoerg MachineBlockFrequencyInfo::getBlockFreq(const MachineBasicBlock *MBB) const {
23106f32e7eSjoerg   return MBFI ? MBFI->getBlockFreq(MBB) : 0;
23206f32e7eSjoerg }
23306f32e7eSjoerg 
getBlockProfileCount(const MachineBasicBlock * MBB) const23406f32e7eSjoerg Optional<uint64_t> MachineBlockFrequencyInfo::getBlockProfileCount(
23506f32e7eSjoerg     const MachineBasicBlock *MBB) const {
236*da58b97aSjoerg   if (!MBFI)
237*da58b97aSjoerg     return None;
238*da58b97aSjoerg 
23906f32e7eSjoerg   const Function &F = MBFI->getFunction()->getFunction();
240*da58b97aSjoerg   return MBFI->getBlockProfileCount(F, MBB);
24106f32e7eSjoerg }
24206f32e7eSjoerg 
24306f32e7eSjoerg Optional<uint64_t>
getProfileCountFromFreq(uint64_t Freq) const24406f32e7eSjoerg MachineBlockFrequencyInfo::getProfileCountFromFreq(uint64_t Freq) const {
245*da58b97aSjoerg   if (!MBFI)
246*da58b97aSjoerg     return None;
247*da58b97aSjoerg 
24806f32e7eSjoerg   const Function &F = MBFI->getFunction()->getFunction();
249*da58b97aSjoerg   return MBFI->getProfileCountFromFreq(F, Freq);
25006f32e7eSjoerg }
25106f32e7eSjoerg 
isIrrLoopHeader(const MachineBasicBlock * MBB) const252*da58b97aSjoerg bool MachineBlockFrequencyInfo::isIrrLoopHeader(
253*da58b97aSjoerg     const MachineBasicBlock *MBB) const {
25406f32e7eSjoerg   assert(MBFI && "Expected analysis to be available");
25506f32e7eSjoerg   return MBFI->isIrrLoopHeader(MBB);
25606f32e7eSjoerg }
25706f32e7eSjoerg 
onEdgeSplit(const MachineBasicBlock & NewPredecessor,const MachineBasicBlock & NewSuccessor,const MachineBranchProbabilityInfo & MBPI)258*da58b97aSjoerg void MachineBlockFrequencyInfo::onEdgeSplit(
259*da58b97aSjoerg     const MachineBasicBlock &NewPredecessor,
260*da58b97aSjoerg     const MachineBasicBlock &NewSuccessor,
261*da58b97aSjoerg     const MachineBranchProbabilityInfo &MBPI) {
262*da58b97aSjoerg   assert(MBFI && "Expected analysis to be available");
263*da58b97aSjoerg   auto NewSuccFreq = MBFI->getBlockFreq(&NewPredecessor) *
264*da58b97aSjoerg                      MBPI.getEdgeProbability(&NewPredecessor, &NewSuccessor);
265*da58b97aSjoerg 
266*da58b97aSjoerg   MBFI->setBlockFreq(&NewSuccessor, NewSuccFreq.getFrequency());
267*da58b97aSjoerg }
268*da58b97aSjoerg 
getFunction() const26906f32e7eSjoerg const MachineFunction *MachineBlockFrequencyInfo::getFunction() const {
27006f32e7eSjoerg   return MBFI ? MBFI->getFunction() : nullptr;
27106f32e7eSjoerg }
27206f32e7eSjoerg 
getMBPI() const27306f32e7eSjoerg const MachineBranchProbabilityInfo *MachineBlockFrequencyInfo::getMBPI() const {
27406f32e7eSjoerg   return MBFI ? &MBFI->getBPI() : nullptr;
27506f32e7eSjoerg }
27606f32e7eSjoerg 
27706f32e7eSjoerg raw_ostream &
printBlockFreq(raw_ostream & OS,const BlockFrequency Freq) const27806f32e7eSjoerg MachineBlockFrequencyInfo::printBlockFreq(raw_ostream &OS,
27906f32e7eSjoerg                                           const BlockFrequency Freq) const {
28006f32e7eSjoerg   return MBFI ? MBFI->printBlockFreq(OS, Freq) : OS;
28106f32e7eSjoerg }
28206f32e7eSjoerg 
28306f32e7eSjoerg raw_ostream &
printBlockFreq(raw_ostream & OS,const MachineBasicBlock * MBB) const28406f32e7eSjoerg MachineBlockFrequencyInfo::printBlockFreq(raw_ostream &OS,
28506f32e7eSjoerg                                           const MachineBasicBlock *MBB) const {
28606f32e7eSjoerg   return MBFI ? MBFI->printBlockFreq(OS, MBB) : OS;
28706f32e7eSjoerg }
28806f32e7eSjoerg 
getEntryFreq() const28906f32e7eSjoerg uint64_t MachineBlockFrequencyInfo::getEntryFreq() const {
29006f32e7eSjoerg   return MBFI ? MBFI->getEntryFreq() : 0;
29106f32e7eSjoerg }
292