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