LCOV - code coverage report
Current view: top level - lib/Analysis - RegionPrinter.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 4 77 5.2 %
Date: 2018-10-20 13:21:21 Functions: 8 22 36.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- RegionPrinter.cpp - Print regions tree pass ------------------------===//
       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             : // Print out the region tree of a function using dotty/graphviz.
      10             : //===----------------------------------------------------------------------===//
      11             : 
      12             : #include "llvm/Analysis/RegionPrinter.h"
      13             : #include "llvm/ADT/DepthFirstIterator.h"
      14             : #include "llvm/ADT/PostOrderIterator.h"
      15             : #include "llvm/ADT/Statistic.h"
      16             : #include "llvm/Analysis/DOTGraphTraitsPass.h"
      17             : #include "llvm/Analysis/Passes.h"
      18             : #include "llvm/Analysis/RegionInfo.h"
      19             : #include "llvm/Analysis/RegionIterator.h"
      20             : #include "llvm/Support/CommandLine.h"
      21             : #include "llvm/Support/Debug.h"
      22             : #include "llvm/Support/raw_ostream.h"
      23             : #ifndef NDEBUG
      24             : #include "llvm/IR/LegacyPassManager.h"
      25             : #endif
      26             : 
      27             : using namespace llvm;
      28             : 
      29             : //===----------------------------------------------------------------------===//
      30             : /// onlySimpleRegion - Show only the simple regions in the RegionViewer.
      31             : static cl::opt<bool>
      32             : onlySimpleRegions("only-simple-regions",
      33             :                   cl::desc("Show only simple regions in the graphviz viewer"),
      34             :                   cl::Hidden,
      35             :                   cl::init(false));
      36             : 
      37             : namespace llvm {
      38             : template<>
      39             : struct DOTGraphTraits<RegionNode*> : public DefaultDOTGraphTraits {
      40             : 
      41             :   DOTGraphTraits (bool isSimple=false)
      42             :     : DefaultDOTGraphTraits(isSimple) {}
      43             : 
      44           0 :   std::string getNodeLabel(RegionNode *Node, RegionNode *Graph) {
      45             : 
      46           0 :     if (!Node->isSubRegion()) {
      47             :       BasicBlock *BB = Node->getNodeAs<BasicBlock>();
      48             : 
      49           0 :       if (isSimple())
      50             :         return DOTGraphTraits<const Function*>
      51           0 :           ::getSimpleNodeLabel(BB, BB->getParent());
      52             :       else
      53             :         return DOTGraphTraits<const Function*>
      54           0 :           ::getCompleteNodeLabel(BB, BB->getParent());
      55             :     }
      56             : 
      57           0 :     return "Not implemented";
      58             :   }
      59             : };
      60             : 
      61             : template <>
      62             : struct DOTGraphTraits<RegionInfo *> : public DOTGraphTraits<RegionNode *> {
      63             : 
      64             :   DOTGraphTraits (bool isSimple = false)
      65             :     : DOTGraphTraits<RegionNode*>(isSimple) {}
      66             : 
      67           0 :   static std::string getGraphName(const RegionInfo *) { return "Region Graph"; }
      68             : 
      69           0 :   std::string getNodeLabel(RegionNode *Node, RegionInfo *G) {
      70             :     return DOTGraphTraits<RegionNode *>::getNodeLabel(
      71           0 :         Node, reinterpret_cast<RegionNode *>(G->getTopLevelRegion()));
      72             :   }
      73             : 
      74           0 :   std::string getEdgeAttributes(RegionNode *srcNode,
      75             :                                 GraphTraits<RegionInfo *>::ChildIteratorType CI,
      76             :                                 RegionInfo *G) {
      77           0 :     RegionNode *destNode = *CI;
      78             : 
      79           0 :     if (srcNode->isSubRegion() || destNode->isSubRegion())
      80           0 :       return "";
      81             : 
      82             :     // In case of a backedge, do not use it to define the layout of the nodes.
      83             :     BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>();
      84             :     BasicBlock *destBB = destNode->getNodeAs<BasicBlock>();
      85             : 
      86           0 :     Region *R = G->getRegionFor(destBB);
      87             : 
      88           0 :     while (R && R->getParent())
      89           0 :       if (R->getParent()->getEntry() == destBB)
      90             :         R = R->getParent();
      91             :       else
      92             :         break;
      93             : 
      94           0 :     if (R && R->getEntry() == destBB && R->contains(srcBB))
      95           0 :       return "constraint=false";
      96             : 
      97           0 :     return "";
      98             :   }
      99             : 
     100             :   // Print the cluster of the subregions. This groups the single basic blocks
     101             :   // and adds a different background color for each group.
     102           0 :   static void printRegionCluster(const Region &R, GraphWriter<RegionInfo *> &GW,
     103             :                                  unsigned depth = 0) {
     104           0 :     raw_ostream &O = GW.getOStream();
     105           0 :     O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void*>(&R)
     106           0 :       << " {\n";
     107           0 :     O.indent(2 * (depth + 1)) << "label = \"\";\n";
     108             : 
     109           0 :     if (!onlySimpleRegions || R.isSimple()) {
     110           0 :       O.indent(2 * (depth + 1)) << "style = filled;\n";
     111           0 :       O.indent(2 * (depth + 1)) << "color = "
     112           0 :         << ((R.getDepth() * 2 % 12) + 1) << "\n";
     113             : 
     114             :     } else {
     115           0 :       O.indent(2 * (depth + 1)) << "style = solid;\n";
     116           0 :       O.indent(2 * (depth + 1)) << "color = "
     117           0 :         << ((R.getDepth() * 2 % 12) + 2) << "\n";
     118             :     }
     119             : 
     120           0 :     for (const auto &RI : R)
     121           0 :       printRegionCluster(*RI, GW, depth + 1);
     122             : 
     123           0 :     const RegionInfo &RI = *static_cast<const RegionInfo*>(R.getRegionInfo());
     124             : 
     125           0 :     for (auto *BB : R.blocks())
     126           0 :       if (RI.getRegionFor(BB) == &R)
     127           0 :         O.indent(2 * (depth + 1)) << "Node"
     128           0 :           << static_cast<const void*>(RI.getTopLevelRegion()->getBBNode(BB))
     129           0 :           << ";\n";
     130             : 
     131           0 :     O.indent(2 * depth) << "}\n";
     132           0 :   }
     133             : 
     134           0 :   static void addCustomGraphFeatures(const RegionInfo *G,
     135             :                                      GraphWriter<RegionInfo *> &GW) {
     136           0 :     raw_ostream &O = GW.getOStream();
     137           0 :     O << "\tcolorscheme = \"paired12\"\n";
     138           0 :     printRegionCluster(*G->getTopLevelRegion(), GW, 4);
     139           0 :   }
     140             : };
     141             : } //end namespace llvm
     142             : 
     143             : namespace {
     144             : 
     145             : struct RegionInfoPassGraphTraits {
     146             :   static RegionInfo *getGraph(RegionInfoPass *RIP) {
     147             :     return &RIP->getRegionInfo();
     148             :   }
     149             : };
     150             : 
     151             : struct RegionPrinter
     152             :     : public DOTGraphTraitsPrinter<RegionInfoPass, false, RegionInfo *,
     153             :                                    RegionInfoPassGraphTraits> {
     154             :   static char ID;
     155           0 :   RegionPrinter()
     156           0 :       : DOTGraphTraitsPrinter<RegionInfoPass, false, RegionInfo *,
     157           0 :                               RegionInfoPassGraphTraits>("reg", ID) {
     158           0 :     initializeRegionPrinterPass(*PassRegistry::getPassRegistry());
     159           0 :   }
     160             : };
     161             : char RegionPrinter::ID = 0;
     162             : 
     163             : struct RegionOnlyPrinter
     164             :     : public DOTGraphTraitsPrinter<RegionInfoPass, true, RegionInfo *,
     165             :                                    RegionInfoPassGraphTraits> {
     166             :   static char ID;
     167           0 :   RegionOnlyPrinter()
     168           0 :       : DOTGraphTraitsPrinter<RegionInfoPass, true, RegionInfo *,
     169           0 :                               RegionInfoPassGraphTraits>("reg", ID) {
     170           0 :     initializeRegionOnlyPrinterPass(*PassRegistry::getPassRegistry());
     171           0 :   }
     172             : };
     173             : char RegionOnlyPrinter::ID = 0;
     174             : 
     175             : struct RegionViewer
     176             :     : public DOTGraphTraitsViewer<RegionInfoPass, false, RegionInfo *,
     177             :                                   RegionInfoPassGraphTraits> {
     178             :   static char ID;
     179           0 :   RegionViewer()
     180           0 :       : DOTGraphTraitsViewer<RegionInfoPass, false, RegionInfo *,
     181           0 :                              RegionInfoPassGraphTraits>("reg", ID) {
     182           0 :     initializeRegionViewerPass(*PassRegistry::getPassRegistry());
     183           0 :   }
     184             : };
     185             : char RegionViewer::ID = 0;
     186             : 
     187             : struct RegionOnlyViewer
     188             :     : public DOTGraphTraitsViewer<RegionInfoPass, true, RegionInfo *,
     189             :                                   RegionInfoPassGraphTraits> {
     190             :   static char ID;
     191           0 :   RegionOnlyViewer()
     192           0 :       : DOTGraphTraitsViewer<RegionInfoPass, true, RegionInfo *,
     193           0 :                              RegionInfoPassGraphTraits>("regonly", ID) {
     194           0 :     initializeRegionOnlyViewerPass(*PassRegistry::getPassRegistry());
     195           0 :   }
     196             : };
     197             : char RegionOnlyViewer::ID = 0;
     198             : 
     199             : } //end anonymous namespace
     200             : 
     201       21512 : INITIALIZE_PASS(RegionPrinter, "dot-regions",
     202             :                 "Print regions of function to 'dot' file", true, true)
     203             : 
     204       21512 : INITIALIZE_PASS(
     205             :     RegionOnlyPrinter, "dot-regions-only",
     206             :     "Print regions of function to 'dot' file (with no function bodies)", true,
     207             :     true)
     208             : 
     209       21512 : INITIALIZE_PASS(RegionViewer, "view-regions", "View regions of function",
     210             :                 true, true)
     211             : 
     212       21512 : INITIALIZE_PASS(RegionOnlyViewer, "view-regions-only",
     213             :                 "View regions of function (with no function bodies)",
     214             :                 true, true)
     215             : 
     216           0 : FunctionPass *llvm::createRegionPrinterPass() { return new RegionPrinter(); }
     217             : 
     218           0 : FunctionPass *llvm::createRegionOnlyPrinterPass() {
     219           0 :   return new RegionOnlyPrinter();
     220             : }
     221             : 
     222           0 : FunctionPass* llvm::createRegionViewerPass() {
     223           0 :   return new RegionViewer();
     224             : }
     225             : 
     226           0 : FunctionPass* llvm::createRegionOnlyViewerPass() {
     227           0 :   return new RegionOnlyViewer();
     228             : }
     229             : 
     230             : #ifndef NDEBUG
     231             : static void viewRegionInfo(RegionInfo *RI, bool ShortNames) {
     232             :   assert(RI && "Argument must be non-null");
     233             : 
     234             :   llvm::Function *F = RI->getTopLevelRegion()->getEntry()->getParent();
     235             :   std::string GraphName = DOTGraphTraits<RegionInfo *>::getGraphName(RI);
     236             : 
     237             :   llvm::ViewGraph(RI, "reg", ShortNames,
     238             :                   Twine(GraphName) + " for '" + F->getName() + "' function");
     239             : }
     240             : 
     241             : static void invokeFunctionPass(const Function *F, FunctionPass *ViewerPass) {
     242             :   assert(F && "Argument must be non-null");
     243             :   assert(!F->isDeclaration() && "Function must have an implementation");
     244             : 
     245             :   // The viewer and analysis passes do not modify anything, so we can safely
     246             :   // remove the const qualifier
     247             :   auto NonConstF = const_cast<Function *>(F);
     248             : 
     249             :   llvm::legacy::FunctionPassManager FPM(NonConstF->getParent());
     250             :   FPM.add(ViewerPass);
     251             :   FPM.doInitialization();
     252             :   FPM.run(*NonConstF);
     253             :   FPM.doFinalization();
     254             : }
     255             : 
     256             : void llvm::viewRegion(RegionInfo *RI) { viewRegionInfo(RI, false); }
     257             : 
     258             : void llvm::viewRegion(const Function *F) {
     259             :   invokeFunctionPass(F, createRegionViewerPass());
     260             : }
     261             : 
     262             : void llvm::viewRegionOnly(RegionInfo *RI) { viewRegionInfo(RI, true); }
     263             : 
     264             : void llvm::viewRegionOnly(const Function *F) {
     265             :   invokeFunctionPass(F, createRegionOnlyViewerPass());
     266             : }
     267             : #endif

Generated by: LCOV version 1.13