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