blob: 8be32d2effa6ea8a8df1b9b2a8e2c1d812fd7cdc [file] [log] [blame]
//===- GIMatchDag.cpp - A DAG representation of a pattern to be matched ---===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "GIMatchDag.h"
#include "llvm/Support/Format.h"
#include "llvm/TableGen/Record.h"
#include "../CodeGenInstruction.h"
using namespace llvm;
void GIMatchDag::writeDOTGraph(raw_ostream &OS, StringRef ID) const {
const auto writePorts = [&](StringRef Prefix,
const GIMatchDagOperandList &Operands) {
StringRef Separator = "";
OS << "{";
for (const auto &Op : enumerate(Operands)) {
OS << Separator << "<" << Prefix << format("%d", Op.index()) << ">"
<< "#" << Op.index() << " $" << Op.value().getName();
Separator = "|";
}
OS << "}";
};
OS << "digraph \"" << ID << "\" {\n"
<< " rankdir=\"BT\"\n";
for (const auto &N : InstrNodes) {
OS << " " << format("Node%p", &*N) << " [shape=record,label=\"{";
writePorts("s", N->getOperandInfo());
OS << "|" << N->getName();
if (N->getOpcodeAnnotation())
OS << "|" << N->getOpcodeAnnotation()->TheDef->getName();
if (N->isMatchRoot())
OS << "|Match starts here";
OS << "|";
SmallVector<std::pair<unsigned, StringRef>, 8> ToPrint;
for (const auto &Assignment : N->user_assigned_operand_names())
ToPrint.emplace_back(Assignment.first, Assignment.second);
llvm::sort(ToPrint);
StringRef Separator = "";
for (const auto &Assignment : ToPrint) {
OS << Separator << "$" << Assignment.second << "=getOperand("
<< Assignment.first << ")";
Separator = ", ";
}
OS << llvm::format("|%p|", &N);
writePorts("d", N->getOperandInfo());
OS << "}\"";
if (N->isMatchRoot())
OS << ",color=red";
OS << "]\n";
}
for (const auto &E : Edges) {
const char *FromFmt = "Node%p:s%d:n";
const char *ToFmt = "Node%p:d%d:s";
if (E->getFromMO()->isDef() && !E->getToMO()->isDef())
std::swap(FromFmt, ToFmt);
auto From = format(FromFmt, E->getFromMI(), E->getFromMO()->getIdx());
auto To = format(ToFmt, E->getToMI(), E->getToMO()->getIdx());
if (E->getFromMO()->isDef() && !E->getToMO()->isDef())
std::swap(From, To);
OS << " " << From << " -> " << To << " [label=\"$" << E->getName();
if (E->getFromMO()->isDef() == E->getToMO()->isDef())
OS << " INVALID EDGE!";
OS << "\"";
if (E->getFromMO()->isDef() == E->getToMO()->isDef())
OS << ",color=red";
else if (E->getFromMO()->isDef() && !E->getToMO()->isDef())
OS << ",dir=back,arrowtail=crow";
OS << "]\n";
}
for (const auto &N : PredicateNodes) {
OS << " " << format("Pred%p", &*N) << " [shape=record,label=\"{";
writePorts("s", N->getOperandInfo());
OS << "|" << N->getName() << "|";
N->printDescription(OS);
OS << llvm::format("|%p|", &N);
writePorts("d", N->getOperandInfo());
OS << "}\",style=dotted]\n";
}
for (const auto &E : PredicateDependencies) {
const char *FromMIFmt = "Node%p:e";
const char *FromMOFmt = "Node%p:s%d:n";
const char *ToFmt = "Pred%p:d%d:s";
auto To = format(ToFmt, E->getPredicate(), E->getPredicateOp()->getIdx());
auto Style = "[style=dotted]";
if (E->getRequiredMO()) {
auto From =
format(FromMOFmt, E->getRequiredMI(), E->getRequiredMO()->getIdx());
OS << " " << From << " -> " << To << " " << Style << "\n";
continue;
}
auto From = format(FromMIFmt, E->getRequiredMI());
OS << " " << From << " -> " << To << " " << Style << "\n";
}
OS << "}\n";
}
LLVM_DUMP_METHOD void GIMatchDag::print(raw_ostream &OS) const {
OS << "matchdag {\n";
for (const auto &N : InstrNodes) {
OS << " ";
N->print(OS);
OS << "\n";
}
for (const auto &E : Edges) {
OS << " ";
E->print(OS);
OS << "\n";
}
for (const auto &P : PredicateNodes) {
OS << " ";
P->print(OS);
OS << "\n";
}
for (const auto &D : PredicateDependencies) {
OS << " ";
D->print(OS);
OS << "\n";
}
OS << "}\n";
}
raw_ostream &llvm::operator<<(raw_ostream &OS, const GIMatchDag &G) {
G.print(OS);
return OS;
}