16eff1278SBardia Mahjour //===- DDGPrinter.cpp - DOT printer for the data dependence graph ----------==//
26eff1278SBardia Mahjour //
36eff1278SBardia Mahjour // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46eff1278SBardia Mahjour // See https://llvm.org/LICENSE.txt for license information.
56eff1278SBardia Mahjour // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66eff1278SBardia Mahjour //
76eff1278SBardia Mahjour //===----------------------------------------------------------------------===//
86eff1278SBardia Mahjour
96eff1278SBardia Mahjour //===----------------------------------------------------------------------===//
106eff1278SBardia Mahjour //
116eff1278SBardia Mahjour // This file defines the `-dot-ddg` analysis pass, which emits DDG in DOT format
126eff1278SBardia Mahjour // in a file named `ddg.<graph-name>.dot` for each loop in a function.
136eff1278SBardia Mahjour //===----------------------------------------------------------------------===//
146eff1278SBardia Mahjour
156eff1278SBardia Mahjour #include "llvm/Analysis/DDGPrinter.h"
166eff1278SBardia Mahjour #include "llvm/Support/CommandLine.h"
176eff1278SBardia Mahjour #include "llvm/Support/GraphWriter.h"
186eff1278SBardia Mahjour
196eff1278SBardia Mahjour using namespace llvm;
206eff1278SBardia Mahjour
21*d86a206fSFangrui Song static cl::opt<bool> DotOnly("dot-ddg-only", cl::Hidden,
22*d86a206fSFangrui Song cl::desc("simple ddg dot graph"));
236eff1278SBardia Mahjour static cl::opt<std::string> DDGDotFilenamePrefix(
246eff1278SBardia Mahjour "dot-ddg-filename-prefix", cl::init("ddg"), cl::Hidden,
256eff1278SBardia Mahjour cl::desc("The prefix used for the DDG dot file names."));
266eff1278SBardia Mahjour
276eff1278SBardia Mahjour static void writeDDGToDotFile(DataDependenceGraph &G, bool DOnly = false);
286eff1278SBardia Mahjour
296eff1278SBardia Mahjour //===--------------------------------------------------------------------===//
306eff1278SBardia Mahjour // Implementation of DDG DOT Printer for a loop
316eff1278SBardia Mahjour //===--------------------------------------------------------------------===//
run(Loop & L,LoopAnalysisManager & AM,LoopStandardAnalysisResults & AR,LPMUpdater & U)326eff1278SBardia Mahjour PreservedAnalyses DDGDotPrinterPass::run(Loop &L, LoopAnalysisManager &AM,
336eff1278SBardia Mahjour LoopStandardAnalysisResults &AR,
346eff1278SBardia Mahjour LPMUpdater &U) {
356eff1278SBardia Mahjour writeDDGToDotFile(*AM.getResult<DDGAnalysis>(L, AR), DotOnly);
366eff1278SBardia Mahjour return PreservedAnalyses::all();
376eff1278SBardia Mahjour }
386eff1278SBardia Mahjour
writeDDGToDotFile(DataDependenceGraph & G,bool DOnly)396eff1278SBardia Mahjour static void writeDDGToDotFile(DataDependenceGraph &G, bool DOnly) {
406eff1278SBardia Mahjour std::string Filename =
416eff1278SBardia Mahjour Twine(DDGDotFilenamePrefix + "." + G.getName() + ".dot").str();
426eff1278SBardia Mahjour errs() << "Writing '" << Filename << "'...";
436eff1278SBardia Mahjour
446eff1278SBardia Mahjour std::error_code EC;
45518d955fSDuncan P. N. Exon Smith raw_fd_ostream File(Filename, EC, sys::fs::OF_Text);
466eff1278SBardia Mahjour
476eff1278SBardia Mahjour if (!EC)
486eff1278SBardia Mahjour // We only provide the constant verson of the DOTGraphTrait specialization,
496eff1278SBardia Mahjour // hence the conversion to const pointer
506eff1278SBardia Mahjour WriteGraph(File, (const DataDependenceGraph *)&G, DOnly);
516eff1278SBardia Mahjour else
526eff1278SBardia Mahjour errs() << " error opening file for writing!";
536eff1278SBardia Mahjour errs() << "\n";
546eff1278SBardia Mahjour }
556eff1278SBardia Mahjour
566eff1278SBardia Mahjour //===--------------------------------------------------------------------===//
576eff1278SBardia Mahjour // DDG DOT Printer Implementation
586eff1278SBardia Mahjour //===--------------------------------------------------------------------===//
getNodeLabel(const DDGNode * Node,const DataDependenceGraph * Graph)596eff1278SBardia Mahjour std::string DDGDotGraphTraits::getNodeLabel(const DDGNode *Node,
606eff1278SBardia Mahjour const DataDependenceGraph *Graph) {
616eff1278SBardia Mahjour if (isSimple())
626eff1278SBardia Mahjour return getSimpleNodeLabel(Node, Graph);
636eff1278SBardia Mahjour else
646eff1278SBardia Mahjour return getVerboseNodeLabel(Node, Graph);
656eff1278SBardia Mahjour }
666eff1278SBardia Mahjour
getEdgeAttributes(const DDGNode * Node,GraphTraits<const DDGNode * >::ChildIteratorType I,const DataDependenceGraph * G)676eff1278SBardia Mahjour std::string DDGDotGraphTraits::getEdgeAttributes(
686eff1278SBardia Mahjour const DDGNode *Node, GraphTraits<const DDGNode *>::ChildIteratorType I,
696eff1278SBardia Mahjour const DataDependenceGraph *G) {
706eff1278SBardia Mahjour const DDGEdge *E = static_cast<const DDGEdge *>(*I.getCurrent());
716eff1278SBardia Mahjour if (isSimple())
726eff1278SBardia Mahjour return getSimpleEdgeAttributes(Node, E, G);
736eff1278SBardia Mahjour else
746eff1278SBardia Mahjour return getVerboseEdgeAttributes(Node, E, G);
756eff1278SBardia Mahjour }
766eff1278SBardia Mahjour
isNodeHidden(const DDGNode * Node,const DataDependenceGraph * Graph)776eff1278SBardia Mahjour bool DDGDotGraphTraits::isNodeHidden(const DDGNode *Node,
786eff1278SBardia Mahjour const DataDependenceGraph *Graph) {
796eff1278SBardia Mahjour if (isSimple() && isa<RootDDGNode>(Node))
806eff1278SBardia Mahjour return true;
816eff1278SBardia Mahjour assert(Graph && "expected a valid graph pointer");
826eff1278SBardia Mahjour return Graph->getPiBlock(*Node) != nullptr;
836eff1278SBardia Mahjour }
846eff1278SBardia Mahjour
856eff1278SBardia Mahjour std::string
getSimpleNodeLabel(const DDGNode * Node,const DataDependenceGraph * G)866eff1278SBardia Mahjour DDGDotGraphTraits::getSimpleNodeLabel(const DDGNode *Node,
876eff1278SBardia Mahjour const DataDependenceGraph *G) {
886eff1278SBardia Mahjour std::string Str;
896eff1278SBardia Mahjour raw_string_ostream OS(Str);
906eff1278SBardia Mahjour if (isa<SimpleDDGNode>(Node))
916eff1278SBardia Mahjour for (auto *II : static_cast<const SimpleDDGNode *>(Node)->getInstructions())
926eff1278SBardia Mahjour OS << *II << "\n";
936eff1278SBardia Mahjour else if (isa<PiBlockDDGNode>(Node))
946eff1278SBardia Mahjour OS << "pi-block\nwith\n"
956eff1278SBardia Mahjour << cast<PiBlockDDGNode>(Node)->getNodes().size() << " nodes\n";
966eff1278SBardia Mahjour else if (isa<RootDDGNode>(Node))
976eff1278SBardia Mahjour OS << "root\n";
986eff1278SBardia Mahjour else
996eff1278SBardia Mahjour llvm_unreachable("Unimplemented type of node");
1006eff1278SBardia Mahjour return OS.str();
1016eff1278SBardia Mahjour }
1026eff1278SBardia Mahjour
1036eff1278SBardia Mahjour std::string
getVerboseNodeLabel(const DDGNode * Node,const DataDependenceGraph * G)1046eff1278SBardia Mahjour DDGDotGraphTraits::getVerboseNodeLabel(const DDGNode *Node,
1056eff1278SBardia Mahjour const DataDependenceGraph *G) {
1066eff1278SBardia Mahjour std::string Str;
1076eff1278SBardia Mahjour raw_string_ostream OS(Str);
1086eff1278SBardia Mahjour OS << "<kind:" << Node->getKind() << ">\n";
1096eff1278SBardia Mahjour if (isa<SimpleDDGNode>(Node))
1106eff1278SBardia Mahjour for (auto *II : static_cast<const SimpleDDGNode *>(Node)->getInstructions())
1116eff1278SBardia Mahjour OS << *II << "\n";
1126eff1278SBardia Mahjour else if (isa<PiBlockDDGNode>(Node)) {
1136eff1278SBardia Mahjour OS << "--- start of nodes in pi-block ---\n";
1146eff1278SBardia Mahjour unsigned Count = 0;
1156eff1278SBardia Mahjour const auto &PNodes = cast<PiBlockDDGNode>(Node)->getNodes();
1166eff1278SBardia Mahjour for (auto *PN : PNodes) {
1176eff1278SBardia Mahjour OS << getVerboseNodeLabel(PN, G);
1186eff1278SBardia Mahjour if (++Count != PNodes.size())
1196eff1278SBardia Mahjour OS << "\n";
1206eff1278SBardia Mahjour }
1216eff1278SBardia Mahjour OS << "--- end of nodes in pi-block ---\n";
1226eff1278SBardia Mahjour } else if (isa<RootDDGNode>(Node))
1236eff1278SBardia Mahjour OS << "root\n";
1246eff1278SBardia Mahjour else
1256eff1278SBardia Mahjour llvm_unreachable("Unimplemented type of node");
1266eff1278SBardia Mahjour return OS.str();
1276eff1278SBardia Mahjour }
1286eff1278SBardia Mahjour
getSimpleEdgeAttributes(const DDGNode * Src,const DDGEdge * Edge,const DataDependenceGraph * G)1296eff1278SBardia Mahjour std::string DDGDotGraphTraits::getSimpleEdgeAttributes(
1306eff1278SBardia Mahjour const DDGNode *Src, const DDGEdge *Edge, const DataDependenceGraph *G) {
1316eff1278SBardia Mahjour std::string Str;
1326eff1278SBardia Mahjour raw_string_ostream OS(Str);
1336eff1278SBardia Mahjour DDGEdge::EdgeKind Kind = Edge->getKind();
1346eff1278SBardia Mahjour OS << "label=\"[" << Kind << "]\"";
1356eff1278SBardia Mahjour return OS.str();
1366eff1278SBardia Mahjour }
1376eff1278SBardia Mahjour
getVerboseEdgeAttributes(const DDGNode * Src,const DDGEdge * Edge,const DataDependenceGraph * G)1386eff1278SBardia Mahjour std::string DDGDotGraphTraits::getVerboseEdgeAttributes(
1396eff1278SBardia Mahjour const DDGNode *Src, const DDGEdge *Edge, const DataDependenceGraph *G) {
1406eff1278SBardia Mahjour std::string Str;
1416eff1278SBardia Mahjour raw_string_ostream OS(Str);
1426eff1278SBardia Mahjour DDGEdge::EdgeKind Kind = Edge->getKind();
1436eff1278SBardia Mahjour OS << "label=\"[";
1446eff1278SBardia Mahjour if (Kind == DDGEdge::EdgeKind::MemoryDependence)
1456eff1278SBardia Mahjour OS << G->getDependenceString(*Src, Edge->getTargetNode());
1466eff1278SBardia Mahjour else
1476eff1278SBardia Mahjour OS << Kind;
1486eff1278SBardia Mahjour OS << "]\"";
1496eff1278SBardia Mahjour return OS.str();
1506eff1278SBardia Mahjour }
151