1//===- MachineBlockFrequencyInfo.cpp - MBB Frequency Analysis -------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Loops should be simplified before this analysis.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
15#include "llvm/Analysis/BlockFrequencyInfoImpl.h"
16#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
17#include "llvm/CodeGen/MachineFunction.h"
18#include "llvm/CodeGen/MachineLoopInfo.h"
19#include "llvm/CodeGen/Passes.h"
20#include "llvm/InitializePasses.h"
21#include "llvm/Support/CommandLine.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/GraphWriter.h"
24
25using namespace llvm;
26
27#define DEBUG_TYPE "block-freq"
28
29#ifndef NDEBUG
30enum GVDAGType {
31  GVDT_None,
32  GVDT_Fraction,
33  GVDT_Integer
34};
35
36static cl::opt<GVDAGType>
37ViewMachineBlockFreqPropagationDAG("view-machine-block-freq-propagation-dags",
38                                   cl::Hidden,
39          cl::desc("Pop up a window to show a dag displaying how machine block "
40                   "frequencies propagate through the CFG."),
41          cl::values(
42            clEnumValN(GVDT_None, "none",
43                       "do not display graphs."),
44            clEnumValN(GVDT_Fraction, "fraction", "display a graph using the "
45                       "fractional block frequency representation."),
46            clEnumValN(GVDT_Integer, "integer", "display a graph using the raw "
47                       "integer fractional block frequency representation."),
48            clEnumValEnd));
49
50namespace llvm {
51
52template <>
53struct GraphTraits<MachineBlockFrequencyInfo *> {
54  typedef const MachineBasicBlock NodeType;
55  typedef MachineBasicBlock::const_succ_iterator ChildIteratorType;
56  typedef MachineFunction::const_iterator nodes_iterator;
57
58  static inline
59  const NodeType *getEntryNode(const MachineBlockFrequencyInfo *G) {
60    return G->getFunction()->begin();
61  }
62
63  static ChildIteratorType child_begin(const NodeType *N) {
64    return N->succ_begin();
65  }
66
67  static ChildIteratorType child_end(const NodeType *N) {
68    return N->succ_end();
69  }
70
71  static nodes_iterator nodes_begin(const MachineBlockFrequencyInfo *G) {
72    return G->getFunction()->begin();
73  }
74
75  static nodes_iterator nodes_end(const MachineBlockFrequencyInfo *G) {
76    return G->getFunction()->end();
77  }
78};
79
80template<>
81struct DOTGraphTraits<MachineBlockFrequencyInfo*> :
82    public DefaultDOTGraphTraits {
83  explicit DOTGraphTraits(bool isSimple=false) :
84    DefaultDOTGraphTraits(isSimple) {}
85
86  static std::string getGraphName(const MachineBlockFrequencyInfo *G) {
87    return G->getFunction()->getName();
88  }
89
90  std::string getNodeLabel(const MachineBasicBlock *Node,
91                           const MachineBlockFrequencyInfo *Graph) {
92    std::string Result;
93    raw_string_ostream OS(Result);
94
95    OS << Node->getName().str() << ":";
96    switch (ViewMachineBlockFreqPropagationDAG) {
97    case GVDT_Fraction:
98      Graph->printBlockFreq(OS, Node);
99      break;
100    case GVDT_Integer:
101      OS << Graph->getBlockFreq(Node).getFrequency();
102      break;
103    case GVDT_None:
104      llvm_unreachable("If we are not supposed to render a graph we should "
105                       "never reach this point.");
106    }
107
108    return Result;
109  }
110};
111
112
113} // end namespace llvm
114#endif
115
116INITIALIZE_PASS_BEGIN(MachineBlockFrequencyInfo, "machine-block-freq",
117                      "Machine Block Frequency Analysis", true, true)
118INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
119INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
120INITIALIZE_PASS_END(MachineBlockFrequencyInfo, "machine-block-freq",
121                    "Machine Block Frequency Analysis", true, true)
122
123char MachineBlockFrequencyInfo::ID = 0;
124
125
126MachineBlockFrequencyInfo::
127MachineBlockFrequencyInfo() :MachineFunctionPass(ID) {
128  initializeMachineBlockFrequencyInfoPass(*PassRegistry::getPassRegistry());
129}
130
131MachineBlockFrequencyInfo::~MachineBlockFrequencyInfo() {}
132
133void MachineBlockFrequencyInfo::getAnalysisUsage(AnalysisUsage &AU) const {
134  AU.addRequired<MachineBranchProbabilityInfo>();
135  AU.addRequired<MachineLoopInfo>();
136  AU.setPreservesAll();
137  MachineFunctionPass::getAnalysisUsage(AU);
138}
139
140bool MachineBlockFrequencyInfo::runOnMachineFunction(MachineFunction &F) {
141  MachineBranchProbabilityInfo &MBPI =
142      getAnalysis<MachineBranchProbabilityInfo>();
143  MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
144  if (!MBFI)
145    MBFI.reset(new ImplType);
146  MBFI->doFunction(&F, &MBPI, &MLI);
147#ifndef NDEBUG
148  if (ViewMachineBlockFreqPropagationDAG != GVDT_None) {
149    view();
150  }
151#endif
152  return false;
153}
154
155void MachineBlockFrequencyInfo::releaseMemory() { MBFI.reset(); }
156
157/// Pop up a ghostview window with the current block frequency propagation
158/// rendered using dot.
159void MachineBlockFrequencyInfo::view() const {
160// This code is only for debugging.
161#ifndef NDEBUG
162  ViewGraph(const_cast<MachineBlockFrequencyInfo *>(this),
163            "MachineBlockFrequencyDAGs");
164#else
165  errs() << "MachineBlockFrequencyInfo::view is only available in debug builds "
166    "on systems with Graphviz or gv!\n";
167#endif // NDEBUG
168}
169
170BlockFrequency MachineBlockFrequencyInfo::
171getBlockFreq(const MachineBasicBlock *MBB) const {
172  return MBFI ? MBFI->getBlockFreq(MBB) : 0;
173}
174
175const MachineFunction *MachineBlockFrequencyInfo::getFunction() const {
176  return MBFI ? MBFI->getFunction() : nullptr;
177}
178
179raw_ostream &
180MachineBlockFrequencyInfo::printBlockFreq(raw_ostream &OS,
181                                          const BlockFrequency Freq) const {
182  return MBFI ? MBFI->printBlockFreq(OS, Freq) : OS;
183}
184
185raw_ostream &
186MachineBlockFrequencyInfo::printBlockFreq(raw_ostream &OS,
187                                          const MachineBasicBlock *MBB) const {
188  return MBFI ? MBFI->printBlockFreq(OS, MBB) : OS;
189}
190
191uint64_t MachineBlockFrequencyInfo::getEntryFreq() const {
192  return MBFI ? MBFI->getEntryFreq() : 0;
193}
194