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