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