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