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