//===- DDGPrinter.cpp - DOT printer for the data dependence graph ----------==// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // // This file defines the `-dot-ddg` analysis pass, which emits DDG in DOT format // in a file named `ddg..dot` for each loop in a function. //===----------------------------------------------------------------------===// #include "llvm/Analysis/DDGPrinter.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/GraphWriter.h" using namespace llvm; static cl::opt DotOnly("dot-ddg-only", cl::init(false), cl::Hidden, cl::ZeroOrMore, cl::desc("simple ddg dot graph")); static cl::opt DDGDotFilenamePrefix( "dot-ddg-filename-prefix", cl::init("ddg"), cl::Hidden, cl::desc("The prefix used for the DDG dot file names.")); static void writeDDGToDotFile(DataDependenceGraph &G, bool DOnly = false); //===--------------------------------------------------------------------===// // Implementation of DDG DOT Printer for a loop //===--------------------------------------------------------------------===// PreservedAnalyses DDGDotPrinterPass::run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U) { writeDDGToDotFile(*AM.getResult(L, AR), DotOnly); return PreservedAnalyses::all(); } static void writeDDGToDotFile(DataDependenceGraph &G, bool DOnly) { std::string Filename = Twine(DDGDotFilenamePrefix + "." + G.getName() + ".dot").str(); errs() << "Writing '" << Filename << "'..."; std::error_code EC; raw_fd_ostream File(Filename, EC, sys::fs::F_Text); if (!EC) // We only provide the constant verson of the DOTGraphTrait specialization, // hence the conversion to const pointer WriteGraph(File, (const DataDependenceGraph *)&G, DOnly); else errs() << " error opening file for writing!"; errs() << "\n"; } //===--------------------------------------------------------------------===// // DDG DOT Printer Implementation //===--------------------------------------------------------------------===// std::string DDGDotGraphTraits::getNodeLabel(const DDGNode *Node, const DataDependenceGraph *Graph) { if (isSimple()) return getSimpleNodeLabel(Node, Graph); else return getVerboseNodeLabel(Node, Graph); } std::string DDGDotGraphTraits::getEdgeAttributes( const DDGNode *Node, GraphTraits::ChildIteratorType I, const DataDependenceGraph *G) { const DDGEdge *E = static_cast(*I.getCurrent()); if (isSimple()) return getSimpleEdgeAttributes(Node, E, G); else return getVerboseEdgeAttributes(Node, E, G); } bool DDGDotGraphTraits::isNodeHidden(const DDGNode *Node, const DataDependenceGraph *Graph) { if (isSimple() && isa(Node)) return true; assert(Graph && "expected a valid graph pointer"); return Graph->getPiBlock(*Node) != nullptr; } std::string DDGDotGraphTraits::getSimpleNodeLabel(const DDGNode *Node, const DataDependenceGraph *G) { std::string Str; raw_string_ostream OS(Str); if (isa(Node)) for (auto *II : static_cast(Node)->getInstructions()) OS << *II << "\n"; else if (isa(Node)) OS << "pi-block\nwith\n" << cast(Node)->getNodes().size() << " nodes\n"; else if (isa(Node)) OS << "root\n"; else llvm_unreachable("Unimplemented type of node"); return OS.str(); } std::string DDGDotGraphTraits::getVerboseNodeLabel(const DDGNode *Node, const DataDependenceGraph *G) { std::string Str; raw_string_ostream OS(Str); OS << "getKind() << ">\n"; if (isa(Node)) for (auto *II : static_cast(Node)->getInstructions()) OS << *II << "\n"; else if (isa(Node)) { OS << "--- start of nodes in pi-block ---\n"; unsigned Count = 0; const auto &PNodes = cast(Node)->getNodes(); for (auto *PN : PNodes) { OS << getVerboseNodeLabel(PN, G); if (++Count != PNodes.size()) OS << "\n"; } OS << "--- end of nodes in pi-block ---\n"; } else if (isa(Node)) OS << "root\n"; else llvm_unreachable("Unimplemented type of node"); return OS.str(); } std::string DDGDotGraphTraits::getSimpleEdgeAttributes( const DDGNode *Src, const DDGEdge *Edge, const DataDependenceGraph *G) { std::string Str; raw_string_ostream OS(Str); DDGEdge::EdgeKind Kind = Edge->getKind(); OS << "label=\"[" << Kind << "]\""; return OS.str(); } std::string DDGDotGraphTraits::getVerboseEdgeAttributes( const DDGNode *Src, const DDGEdge *Edge, const DataDependenceGraph *G) { std::string Str; raw_string_ostream OS(Str); DDGEdge::EdgeKind Kind = Edge->getKind(); OS << "label=\"["; if (Kind == DDGEdge::EdgeKind::MemoryDependence) OS << G->getDependenceString(*Src, Edge->getTargetNode()); else OS << Kind; OS << "]\""; return OS.str(); }