1356843Sdim//===- GIMatchDag.cpp - A DAG representation of a pattern to be matched ---===// 2356843Sdim// 3356843Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4356843Sdim// See https://llvm.org/LICENSE.txt for license information. 5356843Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6356843Sdim// 7356843Sdim//===----------------------------------------------------------------------===// 8356843Sdim 9356843Sdim#include "GIMatchDag.h" 10356843Sdim 11356843Sdim#include "llvm/Support/Format.h" 12356843Sdim#include "llvm/TableGen/Record.h" 13356843Sdim#include "../CodeGenInstruction.h" 14356843Sdim 15356843Sdimusing namespace llvm; 16356843Sdim 17356843Sdimvoid GIMatchDag::writeDOTGraph(raw_ostream &OS, StringRef ID) const { 18356843Sdim const auto writePorts = [&](StringRef Prefix, 19356843Sdim const GIMatchDagOperandList &Operands) { 20356843Sdim StringRef Separator = ""; 21356843Sdim OS << "{"; 22356843Sdim for (const auto &Op : enumerate(Operands)) { 23356843Sdim OS << Separator << "<" << Prefix << format("%d", Op.index()) << ">" 24356843Sdim << "#" << Op.index() << " $" << Op.value().getName(); 25356843Sdim Separator = "|"; 26356843Sdim } 27356843Sdim OS << "}"; 28356843Sdim }; 29356843Sdim 30356843Sdim OS << "digraph \"" << ID << "\" {\n" 31356843Sdim << " rankdir=\"BT\"\n"; 32356843Sdim for (const auto &N : InstrNodes) { 33356843Sdim OS << " " << format("Node%p", &*N) << " [shape=record,label=\"{"; 34356843Sdim writePorts("s", N->getOperandInfo()); 35356843Sdim OS << "|" << N->getName(); 36356843Sdim if (N->getOpcodeAnnotation()) 37356843Sdim OS << "|" << N->getOpcodeAnnotation()->TheDef->getName(); 38356843Sdim if (N->isMatchRoot()) 39356843Sdim OS << "|Match starts here"; 40356843Sdim OS << "|"; 41356843Sdim SmallVector<std::pair<unsigned, StringRef>, 8> ToPrint; 42356843Sdim for (const auto &Assignment : N->user_assigned_operand_names()) 43356843Sdim ToPrint.emplace_back(Assignment.first, Assignment.second); 44356843Sdim llvm::sort(ToPrint.begin(), ToPrint.end()); 45356843Sdim StringRef Separator = ""; 46356843Sdim for (const auto &Assignment : ToPrint) { 47356843Sdim OS << Separator << "$" << Assignment.second << "=getOperand(" 48356843Sdim << Assignment.first << ")"; 49356843Sdim Separator = ", "; 50356843Sdim } 51356843Sdim OS << format("|%p|", &N); 52356843Sdim writePorts("d", N->getOperandInfo()); 53356843Sdim OS << "}\""; 54356843Sdim if (N->isMatchRoot()) 55356843Sdim OS << ",color=red"; 56356843Sdim OS << "]\n"; 57356843Sdim } 58356843Sdim 59356843Sdim for (const auto &E : Edges) { 60356843Sdim const char *FromFmt = "Node%p:s%d:n"; 61356843Sdim const char *ToFmt = "Node%p:d%d:s"; 62356843Sdim if (E->getFromMO()->isDef() && !E->getToMO()->isDef()) 63356843Sdim std::swap(FromFmt, ToFmt); 64356843Sdim auto From = format(FromFmt, E->getFromMI(), E->getFromMO()->getIdx()); 65356843Sdim auto To = format(ToFmt, E->getToMI(), E->getToMO()->getIdx()); 66356843Sdim if (E->getFromMO()->isDef() && !E->getToMO()->isDef()) 67356843Sdim std::swap(From, To); 68356843Sdim 69356843Sdim OS << " " << From << " -> " << To << " [label=\"$" << E->getName(); 70356843Sdim if (E->getFromMO()->isDef() == E->getToMO()->isDef()) 71356843Sdim OS << " INVALID EDGE!"; 72356843Sdim OS << "\""; 73356843Sdim if (E->getFromMO()->isDef() == E->getToMO()->isDef()) 74356843Sdim OS << ",color=red"; 75356843Sdim else if (E->getFromMO()->isDef() && !E->getToMO()->isDef()) 76356843Sdim OS << ",dir=back,arrowtail=crow"; 77356843Sdim OS << "]\n"; 78356843Sdim } 79356843Sdim 80356843Sdim for (const auto &N : PredicateNodes) { 81356843Sdim OS << " " << format("Pred%p", &*N) << " [shape=record,label=\"{"; 82356843Sdim writePorts("s", N->getOperandInfo()); 83356843Sdim OS << "|" << N->getName() << "|"; 84356843Sdim N->printDescription(OS); 85356843Sdim OS << format("|%p|", &N); 86356843Sdim writePorts("d", N->getOperandInfo()); 87356843Sdim OS << "}\",style=dotted]\n"; 88356843Sdim } 89356843Sdim 90356843Sdim for (const auto &E : PredicateDependencies) { 91356843Sdim const char *FromMIFmt = "Node%p:e"; 92356843Sdim const char *FromMOFmt = "Node%p:s%d:n"; 93356843Sdim const char *ToFmt = "Pred%p:d%d:s"; 94356843Sdim auto To = format(ToFmt, E->getPredicate(), E->getPredicateOp()->getIdx()); 95356843Sdim auto Style = "[style=dotted]"; 96356843Sdim if (E->getRequiredMO()) { 97356843Sdim auto From = 98356843Sdim format(FromMOFmt, E->getRequiredMI(), E->getRequiredMO()->getIdx()); 99356843Sdim OS << " " << From << " -> " << To << " " << Style << "\n"; 100356843Sdim continue; 101356843Sdim } 102356843Sdim auto From = format(FromMIFmt, E->getRequiredMI()); 103356843Sdim OS << " " << From << " -> " << To << " " << Style << "\n"; 104356843Sdim } 105356843Sdim 106356843Sdim OS << "}\n"; 107356843Sdim} 108356843Sdim 109356843SdimLLVM_DUMP_METHOD void GIMatchDag::print(raw_ostream &OS) const { 110356843Sdim OS << "matchdag {\n"; 111356843Sdim for (const auto &N : InstrNodes) { 112356843Sdim OS << " "; 113356843Sdim N->print(OS); 114356843Sdim OS << "\n"; 115356843Sdim } 116356843Sdim for (const auto &E : Edges) { 117356843Sdim OS << " "; 118356843Sdim E->print(OS); 119356843Sdim OS << "\n"; 120356843Sdim } 121356843Sdim 122356843Sdim for (const auto &P : PredicateNodes) { 123356843Sdim OS << " "; 124356843Sdim P->print(OS); 125356843Sdim OS << "\n"; 126356843Sdim } 127356843Sdim for (const auto &D : PredicateDependencies) { 128356843Sdim OS << " "; 129356843Sdim D->print(OS); 130356843Sdim OS << "\n"; 131356843Sdim } 132356843Sdim OS << "}\n"; 133356843Sdim} 134356843Sdim 135356843Sdimraw_ostream &llvm::operator<<(raw_ostream &OS, const GIMatchDag &G) { 136356843Sdim G.print(OS); 137356843Sdim return OS; 138356843Sdim} 139