regionprinter.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. #include "llvm/Analysis/Passes.h"
  12. #include "llvm/ADT/DepthFirstIterator.h"
  13. #include "llvm/ADT/PostOrderIterator.h"
  14. #include "llvm/ADT/Statistic.h"
  15. #include "llvm/Analysis/DOTGraphTraitsPass.h"
  16. #include "llvm/Analysis/RegionInfo.h"
  17. #include "llvm/Analysis/RegionIterator.h"
  18. #include "llvm/Analysis/RegionPrinter.h"
  19. #include "llvm/Support/CommandLine.h"
  20. #include "llvm/Support/Debug.h"
  21. #include "llvm/Support/raw_ostream.h"
  22. using namespace llvm;
  23. //===----------------------------------------------------------------------===//
  24. /// onlySimpleRegion - Show only the simple regions in the RegionViewer.
  25. static cl::opt<bool>
  26. onlySimpleRegions("only-simple-regions",
  27. cl::desc("Show only simple regions in the graphviz viewer"),
  28. cl::Hidden,
  29. cl::init(false));
  30. namespace llvm {
  31. template<>
  32. struct DOTGraphTraits<RegionNode*> : public DefaultDOTGraphTraits {
  33. DOTGraphTraits (bool isSimple=false)
  34. : DefaultDOTGraphTraits(isSimple) {}
  35. std::string getNodeLabel(RegionNode *Node, RegionNode *Graph) {
  36. if (!Node->isSubRegion()) {
  37. BasicBlock *BB = Node->getNodeAs<BasicBlock>();
  38. if (isSimple())
  39. return DOTGraphTraits<const Function*>
  40. ::getSimpleNodeLabel(BB, BB->getParent());
  41. else
  42. return DOTGraphTraits<const Function*>
  43. ::getCompleteNodeLabel(BB, BB->getParent());
  44. }
  45. return "Not implemented";
  46. }
  47. };
  48. template<>
  49. struct DOTGraphTraits<RegionInfoPass*> : public DOTGraphTraits<RegionNode*> {
  50. DOTGraphTraits (bool isSimple = false)
  51. : DOTGraphTraits<RegionNode*>(isSimple) {}
  52. static std::string getGraphName(RegionInfoPass *DT) {
  53. return "Region Graph";
  54. }
  55. std::string getNodeLabel(RegionNode *Node, RegionInfoPass *G) {
  56. RegionInfo &RI = G->getRegionInfo();
  57. return DOTGraphTraits<RegionNode*>::getNodeLabel(Node,
  58. reinterpret_cast<RegionNode*>(RI.getTopLevelRegion()));
  59. }
  60. std::string getEdgeAttributes(RegionNode *srcNode,
  61. GraphTraits<RegionInfo*>::ChildIteratorType CI, RegionInfoPass *G) {
  62. RegionInfo &RI = G->getRegionInfo();
  63. RegionNode *destNode = *CI;
  64. if (srcNode->isSubRegion() || destNode->isSubRegion())
  65. return "";
  66. // In case of a backedge, do not use it to define the layout of the nodes.
  67. BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>();
  68. BasicBlock *destBB = destNode->getNodeAs<BasicBlock>();
  69. Region *R = RI.getRegionFor(destBB);
  70. while (R && R->getParent())
  71. if (R->getParent()->getEntry() == destBB)
  72. R = R->getParent();
  73. else
  74. break;
  75. if (R && R->getEntry() == destBB && R->contains(srcBB)) // HLSL Change - add null check
  76. return "constraint=false";
  77. return "";
  78. }
  79. // Print the cluster of the subregions. This groups the single basic blocks
  80. // and adds a different background color for each group.
  81. static void printRegionCluster(const Region &R,
  82. GraphWriter<RegionInfoPass*> &GW,
  83. unsigned depth = 0) {
  84. raw_ostream &O = GW.getOStream();
  85. O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void*>(&R)
  86. << " {\n";
  87. O.indent(2 * (depth + 1)) << "label = \"\";\n";
  88. if (!onlySimpleRegions || R.isSimple()) {
  89. O.indent(2 * (depth + 1)) << "style = filled;\n";
  90. O.indent(2 * (depth + 1)) << "color = "
  91. << ((R.getDepth() * 2 % 12) + 1) << "\n";
  92. } else {
  93. O.indent(2 * (depth + 1)) << "style = solid;\n";
  94. O.indent(2 * (depth + 1)) << "color = "
  95. << ((R.getDepth() * 2 % 12) + 2) << "\n";
  96. }
  97. for (Region::const_iterator RI = R.begin(), RE = R.end(); RI != RE; ++RI)
  98. printRegionCluster(**RI, GW, depth + 1);
  99. const RegionInfo &RI = *static_cast<const RegionInfo*>(R.getRegionInfo());
  100. for (auto *BB : R.blocks())
  101. if (RI.getRegionFor(BB) == &R)
  102. O.indent(2 * (depth + 1)) << "Node"
  103. << static_cast<const void*>(RI.getTopLevelRegion()->getBBNode(BB))
  104. << ";\n";
  105. O.indent(2 * depth) << "}\n";
  106. }
  107. static void addCustomGraphFeatures(const RegionInfoPass* RIP,
  108. GraphWriter<RegionInfoPass*> &GW) {
  109. const RegionInfo &RI = RIP->getRegionInfo();
  110. raw_ostream &O = GW.getOStream();
  111. O << "\tcolorscheme = \"paired12\"\n";
  112. printRegionCluster(*RI.getTopLevelRegion(), GW, 4);
  113. }
  114. };
  115. } //end namespace llvm
  116. namespace {
  117. struct RegionViewer
  118. : public DOTGraphTraitsViewer<RegionInfoPass, false> {
  119. static char ID;
  120. RegionViewer() : DOTGraphTraitsViewer<RegionInfoPass, false>("reg", ID){
  121. initializeRegionViewerPass(*PassRegistry::getPassRegistry());
  122. }
  123. };
  124. char RegionViewer::ID = 0;
  125. struct RegionOnlyViewer
  126. : public DOTGraphTraitsViewer<RegionInfoPass, true> {
  127. static char ID;
  128. RegionOnlyViewer() : DOTGraphTraitsViewer<RegionInfoPass, true>("regonly", ID) {
  129. initializeRegionOnlyViewerPass(*PassRegistry::getPassRegistry());
  130. }
  131. };
  132. char RegionOnlyViewer::ID = 0;
  133. struct RegionPrinter
  134. : public DOTGraphTraitsPrinter<RegionInfoPass, false> {
  135. static char ID;
  136. RegionPrinter() :
  137. DOTGraphTraitsPrinter<RegionInfoPass, false>("reg", ID) {
  138. initializeRegionPrinterPass(*PassRegistry::getPassRegistry());
  139. }
  140. };
  141. char RegionPrinter::ID = 0;
  142. } //end anonymous namespace
  143. INITIALIZE_PASS(RegionPrinter, "dot-regions",
  144. "Print regions of function to 'dot' file", true, true)
  145. INITIALIZE_PASS(RegionViewer, "view-regions", "View regions of function",
  146. true, true)
  147. INITIALIZE_PASS(RegionOnlyViewer, "view-regions-only",
  148. "View regions of function (with no function bodies)",
  149. true, true)
  150. namespace {
  151. struct RegionOnlyPrinter
  152. : public DOTGraphTraitsPrinter<RegionInfoPass, true> {
  153. static char ID;
  154. RegionOnlyPrinter() :
  155. DOTGraphTraitsPrinter<RegionInfoPass, true>("reg", ID) {
  156. initializeRegionOnlyPrinterPass(*PassRegistry::getPassRegistry());
  157. }
  158. };
  159. }
  160. char RegionOnlyPrinter::ID = 0;
  161. INITIALIZE_PASS(RegionOnlyPrinter, "dot-regions-only",
  162. "Print regions of function to 'dot' file "
  163. "(with no function bodies)",
  164. true, true)
  165. FunctionPass* llvm::createRegionViewerPass() {
  166. return new RegionViewer();
  167. }
  168. FunctionPass* llvm::createRegionOnlyViewerPass() {
  169. return new RegionOnlyViewer();
  170. }
  171. FunctionPass* llvm::createRegionPrinterPass() {
  172. return new RegionPrinter();
  173. }
  174. FunctionPass* llvm::createRegionOnlyPrinterPass() {
  175. return new RegionOnlyPrinter();
  176. }