LLVM API Documentation

BlockFrequencyInfo.cpp
Go to the documentation of this file.
00001 //===- BlockFrequencyInfo.cpp - Block Frequency Analysis ------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // Loops should be simplified before this analysis.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "llvm/Analysis/BlockFrequencyInfo.h"
00015 #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
00016 #include "llvm/Analysis/BranchProbabilityInfo.h"
00017 #include "llvm/Analysis/LoopInfo.h"
00018 #include "llvm/Analysis/Passes.h"
00019 #include "llvm/IR/CFG.h"
00020 #include "llvm/InitializePasses.h"
00021 #include "llvm/Support/CommandLine.h"
00022 #include "llvm/Support/Debug.h"
00023 #include "llvm/Support/GraphWriter.h"
00024 
00025 using namespace llvm;
00026 
00027 #define DEBUG_TYPE "block-freq"
00028 
00029 #ifndef NDEBUG
00030 enum GVDAGType {
00031   GVDT_None,
00032   GVDT_Fraction,
00033   GVDT_Integer
00034 };
00035 
00036 static cl::opt<GVDAGType>
00037 ViewBlockFreqPropagationDAG("view-block-freq-propagation-dags", cl::Hidden,
00038           cl::desc("Pop up a window to show a dag displaying how block "
00039                    "frequencies propagation through the CFG."),
00040           cl::values(
00041             clEnumValN(GVDT_None, "none",
00042                        "do not display graphs."),
00043             clEnumValN(GVDT_Fraction, "fraction", "display a graph using the "
00044                        "fractional block frequency representation."),
00045             clEnumValN(GVDT_Integer, "integer", "display a graph using the raw "
00046                        "integer fractional block frequency representation."),
00047             clEnumValEnd));
00048 
00049 namespace llvm {
00050 
00051 template <>
00052 struct GraphTraits<BlockFrequencyInfo *> {
00053   typedef const BasicBlock NodeType;
00054   typedef succ_const_iterator ChildIteratorType;
00055   typedef Function::const_iterator nodes_iterator;
00056 
00057   static inline const NodeType *getEntryNode(const BlockFrequencyInfo *G) {
00058     return G->getFunction()->begin();
00059   }
00060   static ChildIteratorType child_begin(const NodeType *N) {
00061     return succ_begin(N);
00062   }
00063   static ChildIteratorType child_end(const NodeType *N) {
00064     return succ_end(N);
00065   }
00066   static nodes_iterator nodes_begin(const BlockFrequencyInfo *G) {
00067     return G->getFunction()->begin();
00068   }
00069   static nodes_iterator nodes_end(const BlockFrequencyInfo *G) {
00070     return G->getFunction()->end();
00071   }
00072 };
00073 
00074 template<>
00075 struct DOTGraphTraits<BlockFrequencyInfo*> : public DefaultDOTGraphTraits {
00076   explicit DOTGraphTraits(bool isSimple=false) :
00077     DefaultDOTGraphTraits(isSimple) {}
00078 
00079   static std::string getGraphName(const BlockFrequencyInfo *G) {
00080     return G->getFunction()->getName();
00081   }
00082 
00083   std::string getNodeLabel(const BasicBlock *Node,
00084                            const BlockFrequencyInfo *Graph) {
00085     std::string Result;
00086     raw_string_ostream OS(Result);
00087 
00088     OS << Node->getName().str() << ":";
00089     switch (ViewBlockFreqPropagationDAG) {
00090     case GVDT_Fraction:
00091       Graph->printBlockFreq(OS, Node);
00092       break;
00093     case GVDT_Integer:
00094       OS << Graph->getBlockFreq(Node).getFrequency();
00095       break;
00096     case GVDT_None:
00097       llvm_unreachable("If we are not supposed to render a graph we should "
00098                        "never reach this point.");
00099     }
00100 
00101     return Result;
00102   }
00103 };
00104 
00105 } // end namespace llvm
00106 #endif
00107 
00108 INITIALIZE_PASS_BEGIN(BlockFrequencyInfo, "block-freq",
00109                       "Block Frequency Analysis", true, true)
00110 INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfo)
00111 INITIALIZE_PASS_DEPENDENCY(LoopInfo)
00112 INITIALIZE_PASS_END(BlockFrequencyInfo, "block-freq",
00113                     "Block Frequency Analysis", true, true)
00114 
00115 char BlockFrequencyInfo::ID = 0;
00116 
00117 
00118 BlockFrequencyInfo::BlockFrequencyInfo() : FunctionPass(ID) {
00119   initializeBlockFrequencyInfoPass(*PassRegistry::getPassRegistry());
00120 }
00121 
00122 BlockFrequencyInfo::~BlockFrequencyInfo() {}
00123 
00124 void BlockFrequencyInfo::getAnalysisUsage(AnalysisUsage &AU) const {
00125   AU.addRequired<BranchProbabilityInfo>();
00126   AU.addRequired<LoopInfo>();
00127   AU.setPreservesAll();
00128 }
00129 
00130 bool BlockFrequencyInfo::runOnFunction(Function &F) {
00131   BranchProbabilityInfo &BPI = getAnalysis<BranchProbabilityInfo>();
00132   LoopInfo &LI = getAnalysis<LoopInfo>();
00133   if (!BFI)
00134     BFI.reset(new ImplType);
00135   BFI->doFunction(&F, &BPI, &LI);
00136 #ifndef NDEBUG
00137   if (ViewBlockFreqPropagationDAG != GVDT_None)
00138     view();
00139 #endif
00140   return false;
00141 }
00142 
00143 void BlockFrequencyInfo::releaseMemory() { BFI.reset(); }
00144 
00145 void BlockFrequencyInfo::print(raw_ostream &O, const Module *) const {
00146   if (BFI) BFI->print(O);
00147 }
00148 
00149 BlockFrequency BlockFrequencyInfo::getBlockFreq(const BasicBlock *BB) const {
00150   return BFI ? BFI->getBlockFreq(BB) : 0;
00151 }
00152 
00153 /// Pop up a ghostview window with the current block frequency propagation
00154 /// rendered using dot.
00155 void BlockFrequencyInfo::view() const {
00156 // This code is only for debugging.
00157 #ifndef NDEBUG
00158   ViewGraph(const_cast<BlockFrequencyInfo *>(this), "BlockFrequencyDAGs");
00159 #else
00160   errs() << "BlockFrequencyInfo::view is only available in debug builds on "
00161             "systems with Graphviz or gv!\n";
00162 #endif // NDEBUG
00163 }
00164 
00165 const Function *BlockFrequencyInfo::getFunction() const {
00166   return BFI ? BFI->getFunction() : nullptr;
00167 }
00168 
00169 raw_ostream &BlockFrequencyInfo::
00170 printBlockFreq(raw_ostream &OS, const BlockFrequency Freq) const {
00171   return BFI ? BFI->printBlockFreq(OS, Freq) : OS;
00172 }
00173 
00174 raw_ostream &
00175 BlockFrequencyInfo::printBlockFreq(raw_ostream &OS,
00176                                    const BasicBlock *BB) const {
00177   return BFI ? BFI->printBlockFreq(OS, BB) : OS;
00178 }
00179 
00180 uint64_t BlockFrequencyInfo::getEntryFreq() const {
00181   return BFI ? BFI->getEntryFreq() : 0;
00182 }