1//===- GIMatchDag.cpp - A DAG representation of a pattern to be matched ---===// 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#include "GIMatchDag.h" 10 11#include "llvm/Support/Format.h" 12#include "llvm/TableGen/Record.h" 13#include "../CodeGenInstruction.h" 14 15using namespace llvm; 16 17void GIMatchDag::writeDOTGraph(raw_ostream &OS, StringRef ID) const { 18 const auto writePorts = [&](StringRef Prefix, 19 const GIMatchDagOperandList &Operands) { 20 StringRef Separator = ""; 21 OS << "{"; 22 for (const auto &Op : enumerate(Operands)) { 23 OS << Separator << "<" << Prefix << format("%d", Op.index()) << ">" 24 << "#" << Op.index() << " $" << Op.value().getName(); 25 Separator = "|"; 26 } 27 OS << "}"; 28 }; 29 30 OS << "digraph \"" << ID << "\" {\n" 31 << " rankdir=\"BT\"\n"; 32 for (const auto &N : InstrNodes) { 33 OS << " " << format("Node%p", &*N) << " [shape=record,label=\"{"; 34 writePorts("s", N->getOperandInfo()); 35 OS << "|" << N->getName(); 36 if (N->getOpcodeAnnotation()) 37 OS << "|" << N->getOpcodeAnnotation()->TheDef->getName(); 38 if (N->isMatchRoot()) 39 OS << "|Match starts here"; 40 OS << "|"; 41 SmallVector<std::pair<unsigned, StringRef>, 8> ToPrint; 42 for (const auto &Assignment : N->user_assigned_operand_names()) 43 ToPrint.emplace_back(Assignment.first, Assignment.second); 44 llvm::sort(ToPrint.begin(), ToPrint.end()); 45 StringRef Separator = ""; 46 for (const auto &Assignment : ToPrint) { 47 OS << Separator << "$" << Assignment.second << "=getOperand(" 48 << Assignment.first << ")"; 49 Separator = ", "; 50 } 51 OS << format("|%p|", &N); 52 writePorts("d", N->getOperandInfo()); 53 OS << "}\""; 54 if (N->isMatchRoot()) 55 OS << ",color=red"; 56 OS << "]\n"; 57 } 58 59 for (const auto &E : Edges) { 60 const char *FromFmt = "Node%p:s%d:n"; 61 const char *ToFmt = "Node%p:d%d:s"; 62 if (E->getFromMO()->isDef() && !E->getToMO()->isDef()) 63 std::swap(FromFmt, ToFmt); 64 auto From = format(FromFmt, E->getFromMI(), E->getFromMO()->getIdx()); 65 auto To = format(ToFmt, E->getToMI(), E->getToMO()->getIdx()); 66 if (E->getFromMO()->isDef() && !E->getToMO()->isDef()) 67 std::swap(From, To); 68 69 OS << " " << From << " -> " << To << " [label=\"$" << E->getName(); 70 if (E->getFromMO()->isDef() == E->getToMO()->isDef()) 71 OS << " INVALID EDGE!"; 72 OS << "\""; 73 if (E->getFromMO()->isDef() == E->getToMO()->isDef()) 74 OS << ",color=red"; 75 else if (E->getFromMO()->isDef() && !E->getToMO()->isDef()) 76 OS << ",dir=back,arrowtail=crow"; 77 OS << "]\n"; 78 } 79 80 for (const auto &N : PredicateNodes) { 81 OS << " " << format("Pred%p", &*N) << " [shape=record,label=\"{"; 82 writePorts("s", N->getOperandInfo()); 83 OS << "|" << N->getName() << "|"; 84 N->printDescription(OS); 85 OS << format("|%p|", &N); 86 writePorts("d", N->getOperandInfo()); 87 OS << "}\",style=dotted]\n"; 88 } 89 90 for (const auto &E : PredicateDependencies) { 91 const char *FromMIFmt = "Node%p:e"; 92 const char *FromMOFmt = "Node%p:s%d:n"; 93 const char *ToFmt = "Pred%p:d%d:s"; 94 auto To = format(ToFmt, E->getPredicate(), E->getPredicateOp()->getIdx()); 95 auto Style = "[style=dotted]"; 96 if (E->getRequiredMO()) { 97 auto From = 98 format(FromMOFmt, E->getRequiredMI(), E->getRequiredMO()->getIdx()); 99 OS << " " << From << " -> " << To << " " << Style << "\n"; 100 continue; 101 } 102 auto From = format(FromMIFmt, E->getRequiredMI()); 103 OS << " " << From << " -> " << To << " " << Style << "\n"; 104 } 105 106 OS << "}\n"; 107} 108 109LLVM_DUMP_METHOD void GIMatchDag::print(raw_ostream &OS) const { 110 OS << "matchdag {\n"; 111 for (const auto &N : InstrNodes) { 112 OS << " "; 113 N->print(OS); 114 OS << "\n"; 115 } 116 for (const auto &E : Edges) { 117 OS << " "; 118 E->print(OS); 119 OS << "\n"; 120 } 121 122 for (const auto &P : PredicateNodes) { 123 OS << " "; 124 P->print(OS); 125 OS << "\n"; 126 } 127 for (const auto &D : PredicateDependencies) { 128 OS << " "; 129 D->print(OS); 130 OS << "\n"; 131 } 132 OS << "}\n"; 133} 134 135raw_ostream &llvm::operator<<(raw_ostream &OS, const GIMatchDag &G) { 136 G.print(OS); 137 return OS; 138} 139