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