DDGPrinter.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. //===- DDGPrinter.cpp - DOT printer for the data dependence graph ----------==//
  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. //
  10. // This file defines the `-dot-ddg` analysis pass, which emits DDG in DOT format
  11. // in a file named `ddg.<graph-name>.dot` for each loop in a function.
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/Analysis/DDGPrinter.h"
  14. #include "llvm/Support/CommandLine.h"
  15. #include "llvm/Support/GraphWriter.h"
  16. using namespace llvm;
  17. static cl::opt<bool> DotOnly("dot-ddg-only", cl::init(false), cl::Hidden,
  18. cl::ZeroOrMore, cl::desc("simple ddg dot graph"));
  19. static cl::opt<std::string> DDGDotFilenamePrefix(
  20. "dot-ddg-filename-prefix", cl::init("ddg"), cl::Hidden,
  21. cl::desc("The prefix used for the DDG dot file names."));
  22. static void writeDDGToDotFile(DataDependenceGraph &G, bool DOnly = false);
  23. //===--------------------------------------------------------------------===//
  24. // Implementation of DDG DOT Printer for a loop
  25. //===--------------------------------------------------------------------===//
  26. PreservedAnalyses DDGDotPrinterPass::run(Loop &L, LoopAnalysisManager &AM,
  27. LoopStandardAnalysisResults &AR,
  28. LPMUpdater &U) {
  29. writeDDGToDotFile(*AM.getResult<DDGAnalysis>(L, AR), DotOnly);
  30. return PreservedAnalyses::all();
  31. }
  32. static void writeDDGToDotFile(DataDependenceGraph &G, bool DOnly) {
  33. std::string Filename =
  34. Twine(DDGDotFilenamePrefix + "." + G.getName() + ".dot").str();
  35. errs() << "Writing '" << Filename << "'...";
  36. std::error_code EC;
  37. raw_fd_ostream File(Filename, EC, sys::fs::OF_Text);
  38. if (!EC)
  39. // We only provide the constant verson of the DOTGraphTrait specialization,
  40. // hence the conversion to const pointer
  41. WriteGraph(File, (const DataDependenceGraph *)&G, DOnly);
  42. else
  43. errs() << " error opening file for writing!";
  44. errs() << "\n";
  45. }
  46. //===--------------------------------------------------------------------===//
  47. // DDG DOT Printer Implementation
  48. //===--------------------------------------------------------------------===//
  49. std::string DDGDotGraphTraits::getNodeLabel(const DDGNode *Node,
  50. const DataDependenceGraph *Graph) {
  51. if (isSimple())
  52. return getSimpleNodeLabel(Node, Graph);
  53. else
  54. return getVerboseNodeLabel(Node, Graph);
  55. }
  56. std::string DDGDotGraphTraits::getEdgeAttributes(
  57. const DDGNode *Node, GraphTraits<const DDGNode *>::ChildIteratorType I,
  58. const DataDependenceGraph *G) {
  59. const DDGEdge *E = static_cast<const DDGEdge *>(*I.getCurrent());
  60. if (isSimple())
  61. return getSimpleEdgeAttributes(Node, E, G);
  62. else
  63. return getVerboseEdgeAttributes(Node, E, G);
  64. }
  65. bool DDGDotGraphTraits::isNodeHidden(const DDGNode *Node,
  66. const DataDependenceGraph *Graph) {
  67. if (isSimple() && isa<RootDDGNode>(Node))
  68. return true;
  69. assert(Graph && "expected a valid graph pointer");
  70. return Graph->getPiBlock(*Node) != nullptr;
  71. }
  72. std::string
  73. DDGDotGraphTraits::getSimpleNodeLabel(const DDGNode *Node,
  74. const DataDependenceGraph *G) {
  75. std::string Str;
  76. raw_string_ostream OS(Str);
  77. if (isa<SimpleDDGNode>(Node))
  78. for (auto *II : static_cast<const SimpleDDGNode *>(Node)->getInstructions())
  79. OS << *II << "\n";
  80. else if (isa<PiBlockDDGNode>(Node))
  81. OS << "pi-block\nwith\n"
  82. << cast<PiBlockDDGNode>(Node)->getNodes().size() << " nodes\n";
  83. else if (isa<RootDDGNode>(Node))
  84. OS << "root\n";
  85. else
  86. llvm_unreachable("Unimplemented type of node");
  87. return OS.str();
  88. }
  89. std::string
  90. DDGDotGraphTraits::getVerboseNodeLabel(const DDGNode *Node,
  91. const DataDependenceGraph *G) {
  92. std::string Str;
  93. raw_string_ostream OS(Str);
  94. OS << "<kind:" << Node->getKind() << ">\n";
  95. if (isa<SimpleDDGNode>(Node))
  96. for (auto *II : static_cast<const SimpleDDGNode *>(Node)->getInstructions())
  97. OS << *II << "\n";
  98. else if (isa<PiBlockDDGNode>(Node)) {
  99. OS << "--- start of nodes in pi-block ---\n";
  100. unsigned Count = 0;
  101. const auto &PNodes = cast<PiBlockDDGNode>(Node)->getNodes();
  102. for (auto *PN : PNodes) {
  103. OS << getVerboseNodeLabel(PN, G);
  104. if (++Count != PNodes.size())
  105. OS << "\n";
  106. }
  107. OS << "--- end of nodes in pi-block ---\n";
  108. } else if (isa<RootDDGNode>(Node))
  109. OS << "root\n";
  110. else
  111. llvm_unreachable("Unimplemented type of node");
  112. return OS.str();
  113. }
  114. std::string DDGDotGraphTraits::getSimpleEdgeAttributes(
  115. const DDGNode *Src, const DDGEdge *Edge, const DataDependenceGraph *G) {
  116. std::string Str;
  117. raw_string_ostream OS(Str);
  118. DDGEdge::EdgeKind Kind = Edge->getKind();
  119. OS << "label=\"[" << Kind << "]\"";
  120. return OS.str();
  121. }
  122. std::string DDGDotGraphTraits::getVerboseEdgeAttributes(
  123. const DDGNode *Src, const DDGEdge *Edge, const DataDependenceGraph *G) {
  124. std::string Str;
  125. raw_string_ostream OS(Str);
  126. DDGEdge::EdgeKind Kind = Edge->getKind();
  127. OS << "label=\"[";
  128. if (Kind == DDGEdge::EdgeKind::MemoryDependence)
  129. OS << G->getDependenceString(*Src, Edge->getTargetNode());
  130. else
  131. OS << Kind;
  132. OS << "]\"";
  133. return OS.str();
  134. }