ScopGraphPrinter.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. //===- GraphPrinter.cpp - Create a DOT output describing the Scop. --------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Create a DOT output describing the Scop.
  10. //
  11. // For each function a dot file is created that shows the control flow graph of
  12. // the function and highlights the detected Scops.
  13. //
  14. //===----------------------------------------------------------------------===//
  15. #include "polly/ScopGraphPrinter.h"
  16. #include "polly/LinkAllPasses.h"
  17. #include "polly/ScopDetection.h"
  18. #include "llvm/Support/CommandLine.h"
  19. using namespace polly;
  20. using namespace llvm;
  21. static cl::opt<std::string>
  22. ViewFilter("polly-view-only",
  23. cl::desc("Only view functions that match this pattern"),
  24. cl::Hidden, cl::init(""));
  25. static cl::opt<bool> ViewAll("polly-view-all",
  26. cl::desc("Also show functions without any scops"),
  27. cl::Hidden, cl::init(false));
  28. namespace llvm {
  29. std::string DOTGraphTraits<ScopDetection *>::getEdgeAttributes(
  30. RegionNode *srcNode, GraphTraits<RegionInfo *>::ChildIteratorType CI,
  31. ScopDetection *SD) {
  32. RegionNode *destNode = *CI;
  33. if (srcNode->isSubRegion() || destNode->isSubRegion())
  34. return "";
  35. // In case of a backedge, do not use it to define the layout of the nodes.
  36. BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>();
  37. BasicBlock *destBB = destNode->getNodeAs<BasicBlock>();
  38. RegionInfo *RI = SD->getRI();
  39. Region *R = RI->getRegionFor(destBB);
  40. while (R && R->getParent())
  41. if (R->getParent()->getEntry() == destBB)
  42. R = R->getParent();
  43. else
  44. break;
  45. if (R && R->getEntry() == destBB && R->contains(srcBB))
  46. return "constraint=false";
  47. return "";
  48. }
  49. std::string
  50. DOTGraphTraits<ScopDetection *>::escapeString(llvm::StringRef String) {
  51. std::string Escaped;
  52. for (const auto &C : String) {
  53. if (C == '"')
  54. Escaped += '\\';
  55. Escaped += C;
  56. }
  57. return Escaped;
  58. }
  59. void DOTGraphTraits<ScopDetection *>::printRegionCluster(ScopDetection *SD,
  60. const Region *R,
  61. raw_ostream &O,
  62. unsigned depth) {
  63. O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void *>(R)
  64. << " {\n";
  65. unsigned LineBegin, LineEnd;
  66. std::string FileName;
  67. getDebugLocation(R, LineBegin, LineEnd, FileName);
  68. std::string Location;
  69. if (LineBegin != (unsigned)-1) {
  70. Location = escapeString(FileName + ":" + std::to_string(LineBegin) + "-" +
  71. std::to_string(LineEnd) + "\n");
  72. }
  73. std::string ErrorMessage = SD->regionIsInvalidBecause(R);
  74. ErrorMessage = escapeString(ErrorMessage);
  75. O.indent(2 * (depth + 1))
  76. << "label = \"" << Location << ErrorMessage << "\";\n";
  77. if (SD->isMaxRegionInScop(*R)) {
  78. O.indent(2 * (depth + 1)) << "style = filled;\n";
  79. // Set color to green.
  80. O.indent(2 * (depth + 1)) << "color = 3";
  81. } else {
  82. O.indent(2 * (depth + 1)) << "style = solid;\n";
  83. int color = (R->getDepth() * 2 % 12) + 1;
  84. // We do not want green again.
  85. if (color == 3)
  86. color = 6;
  87. O.indent(2 * (depth + 1)) << "color = " << color << "\n";
  88. }
  89. for (const auto &SubRegion : *R)
  90. printRegionCluster(SD, SubRegion.get(), O, depth + 1);
  91. RegionInfo *RI = R->getRegionInfo();
  92. for (BasicBlock *BB : R->blocks())
  93. if (RI->getRegionFor(BB) == R)
  94. O.indent(2 * (depth + 1))
  95. << "Node"
  96. << static_cast<void *>(RI->getTopLevelRegion()->getBBNode(BB))
  97. << ";\n";
  98. O.indent(2 * depth) << "}\n";
  99. }
  100. void DOTGraphTraits<ScopDetection *>::addCustomGraphFeatures(
  101. ScopDetection *SD, GraphWriter<ScopDetection *> &GW) {
  102. raw_ostream &O = GW.getOStream();
  103. O << "\tcolorscheme = \"paired12\"\n";
  104. printRegionCluster(SD, SD->getRI()->getTopLevelRegion(), O, 4);
  105. }
  106. } // namespace llvm
  107. struct ScopDetectionAnalysisGraphTraits {
  108. static ScopDetection *getGraph(ScopDetectionWrapperPass *Analysis) {
  109. return &Analysis->getSD();
  110. }
  111. };
  112. struct ScopViewerWrapperPass
  113. : DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
  114. ScopDetection *,
  115. ScopDetectionAnalysisGraphTraits> {
  116. static char ID;
  117. ScopViewerWrapperPass()
  118. : DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
  119. ScopDetection *,
  120. ScopDetectionAnalysisGraphTraits>(
  121. "scops", ID) {}
  122. bool processFunction(Function &F, ScopDetectionWrapperPass &SD) override {
  123. if (ViewFilter != "" && !F.getName().count(ViewFilter))
  124. return false;
  125. if (ViewAll)
  126. return true;
  127. // Check that at least one scop was detected.
  128. return std::distance(SD.getSD().begin(), SD.getSD().end()) > 0;
  129. }
  130. };
  131. char ScopViewerWrapperPass::ID = 0;
  132. struct ScopOnlyViewerWrapperPass
  133. : DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
  134. ScopDetection *,
  135. ScopDetectionAnalysisGraphTraits> {
  136. static char ID;
  137. ScopOnlyViewerWrapperPass()
  138. : DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
  139. ScopDetection *,
  140. ScopDetectionAnalysisGraphTraits>(
  141. "scopsonly", ID) {}
  142. };
  143. char ScopOnlyViewerWrapperPass::ID = 0;
  144. struct ScopPrinterWrapperPass
  145. : DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, false,
  146. ScopDetection *,
  147. ScopDetectionAnalysisGraphTraits> {
  148. static char ID;
  149. ScopPrinterWrapperPass()
  150. : DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, false,
  151. ScopDetection *,
  152. ScopDetectionAnalysisGraphTraits>(
  153. "scops", ID) {}
  154. };
  155. char ScopPrinterWrapperPass::ID = 0;
  156. struct ScopOnlyPrinterWrapperPass
  157. : DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, true,
  158. ScopDetection *,
  159. ScopDetectionAnalysisGraphTraits> {
  160. static char ID;
  161. ScopOnlyPrinterWrapperPass()
  162. : DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, true,
  163. ScopDetection *,
  164. ScopDetectionAnalysisGraphTraits>(
  165. "scopsonly", ID) {}
  166. };
  167. char ScopOnlyPrinterWrapperPass::ID = 0;
  168. static RegisterPass<ScopViewerWrapperPass> X("view-scops",
  169. "Polly - View Scops of function");
  170. static RegisterPass<ScopOnlyViewerWrapperPass>
  171. Y("view-scops-only",
  172. "Polly - View Scops of function (with no function bodies)");
  173. static RegisterPass<ScopPrinterWrapperPass>
  174. M("dot-scops", "Polly - Print Scops of function");
  175. static RegisterPass<ScopOnlyPrinterWrapperPass>
  176. N("dot-scops-only",
  177. "Polly - Print Scops of function (with no function bodies)");
  178. Pass *polly::createDOTViewerWrapperPass() {
  179. return new ScopViewerWrapperPass();
  180. }
  181. Pass *polly::createDOTOnlyViewerWrapperPass() {
  182. return new ScopOnlyViewerWrapperPass();
  183. }
  184. Pass *polly::createDOTPrinterWrapperPass() {
  185. return new ScopPrinterWrapperPass();
  186. }
  187. Pass *polly::createDOTOnlyPrinterWrapperPass() {
  188. return new ScopOnlyPrinterWrapperPass();
  189. }
  190. bool ScopViewer::processFunction(Function &F, const ScopDetection &SD) {
  191. if (ViewFilter != "" && !F.getName().count(ViewFilter))
  192. return false;
  193. if (ViewAll)
  194. return true;
  195. // Check that at least one scop was detected.
  196. return std::distance(SD.begin(), SD.end()) > 0;
  197. }