123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- //===- 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.<graph-name>.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<bool> DotOnly("dot-ddg-only", cl::init(false), cl::Hidden,
- cl::ZeroOrMore, cl::desc("simple ddg dot graph"));
- static cl::opt<std::string> 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<DDGAnalysis>(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::OF_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<const DDGNode *>::ChildIteratorType I,
- const DataDependenceGraph *G) {
- const DDGEdge *E = static_cast<const DDGEdge *>(*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<RootDDGNode>(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<SimpleDDGNode>(Node))
- for (auto *II : static_cast<const SimpleDDGNode *>(Node)->getInstructions())
- OS << *II << "\n";
- else if (isa<PiBlockDDGNode>(Node))
- OS << "pi-block\nwith\n"
- << cast<PiBlockDDGNode>(Node)->getNodes().size() << " nodes\n";
- else if (isa<RootDDGNode>(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 << "<kind:" << Node->getKind() << ">\n";
- if (isa<SimpleDDGNode>(Node))
- for (auto *II : static_cast<const SimpleDDGNode *>(Node)->getInstructions())
- OS << *II << "\n";
- else if (isa<PiBlockDDGNode>(Node)) {
- OS << "--- start of nodes in pi-block ---\n";
- unsigned Count = 0;
- const auto &PNodes = cast<PiBlockDDGNode>(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<RootDDGNode>(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();
- }
|