1 //===- DDGPrinter.cpp - DOT printer for the data dependence graph ----------==//
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
7 //===----------------------------------------------------------------------===//
9 //===----------------------------------------------------------------------===//
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 //===----------------------------------------------------------------------===//
15 #include "llvm/Analysis/DDGPrinter.h"
16 #include "llvm/Support/CommandLine.h"
17 #include "llvm/Support/GraphWriter.h"
21 static cl::opt
<bool> DotOnly("dot-ddg-only", cl::Hidden
,
22 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."));
27 static void writeDDGToDotFile(DataDependenceGraph
&G
, bool DOnly
= false);
29 //===--------------------------------------------------------------------===//
30 // Implementation of DDG DOT Printer for a loop
31 //===--------------------------------------------------------------------===//
32 PreservedAnalyses
DDGDotPrinterPass::run(Loop
&L
, LoopAnalysisManager
&AM
,
33 LoopStandardAnalysisResults
&AR
,
35 writeDDGToDotFile(*AM
.getResult
<DDGAnalysis
>(L
, AR
), DotOnly
);
36 return PreservedAnalyses::all();
39 static void writeDDGToDotFile(DataDependenceGraph
&G
, bool DOnly
) {
40 std::string Filename
=
41 Twine(DDGDotFilenamePrefix
+ "." + G
.getName() + ".dot").str();
42 errs() << "Writing '" << Filename
<< "'...";
45 raw_fd_ostream
File(Filename
, EC
, sys::fs::OF_Text
);
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
);
52 errs() << " error opening file for writing!";
56 //===--------------------------------------------------------------------===//
57 // DDG DOT Printer Implementation
58 //===--------------------------------------------------------------------===//
59 std::string
DDGDotGraphTraits::getNodeLabel(const DDGNode
*Node
,
60 const DataDependenceGraph
*Graph
) {
62 return getSimpleNodeLabel(Node
, Graph
);
64 return getVerboseNodeLabel(Node
, Graph
);
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());
72 return getSimpleEdgeAttributes(Node
, E
, G
);
74 return getVerboseEdgeAttributes(Node
, E
, G
);
77 bool DDGDotGraphTraits::isNodeHidden(const DDGNode
*Node
,
78 const DataDependenceGraph
*Graph
) {
79 if (isSimple() && isa
<RootDDGNode
>(Node
))
81 assert(Graph
&& "expected a valid graph pointer");
82 return Graph
->getPiBlock(*Node
) != nullptr;
86 DDGDotGraphTraits::getSimpleNodeLabel(const DDGNode
*Node
,
87 const DataDependenceGraph
*G
) {
89 raw_string_ostream
OS(Str
);
90 if (isa
<SimpleDDGNode
>(Node
))
91 for (auto *II
: static_cast<const SimpleDDGNode
*>(Node
)->getInstructions())
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
))
99 llvm_unreachable("Unimplemented type of node");
104 DDGDotGraphTraits::getVerboseNodeLabel(const DDGNode
*Node
,
105 const DataDependenceGraph
*G
) {
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())
112 else if (isa
<PiBlockDDGNode
>(Node
)) {
113 OS
<< "--- start of nodes in pi-block ---\n";
115 const auto &PNodes
= cast
<PiBlockDDGNode
>(Node
)->getNodes();
116 for (auto *PN
: PNodes
) {
117 OS
<< getVerboseNodeLabel(PN
, G
);
118 if (++Count
!= PNodes
.size())
121 OS
<< "--- end of nodes in pi-block ---\n";
122 } else if (isa
<RootDDGNode
>(Node
))
125 llvm_unreachable("Unimplemented type of node");
129 std::string
DDGDotGraphTraits::getSimpleEdgeAttributes(
130 const DDGNode
*Src
, const DDGEdge
*Edge
, const DataDependenceGraph
*G
) {
132 raw_string_ostream
OS(Str
);
133 DDGEdge::EdgeKind Kind
= Edge
->getKind();
134 OS
<< "label=\"[" << Kind
<< "]\"";
138 std::string
DDGDotGraphTraits::getVerboseEdgeAttributes(
139 const DDGNode
*Src
, const DDGEdge
*Edge
, const DataDependenceGraph
*G
) {
141 raw_string_ostream
OS(Str
);
142 DDGEdge::EdgeKind Kind
= Edge
->getKind();
144 if (Kind
== DDGEdge::EdgeKind::MemoryDependence
)
145 OS
<< G
->getDependenceString(*Src
, Edge
->getTargetNode());