Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/Common/DAGISelMatcher.cpp
35290 views
//===- DAGISelMatcher.cpp - Representation of DAG pattern matcher ---------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "DAGISelMatcher.h"9#include "CodeGenDAGPatterns.h"10#include "CodeGenInstruction.h"11#include "CodeGenRegisters.h"12#include "CodeGenTarget.h"13#include "llvm/Support/raw_ostream.h"14#include "llvm/TableGen/Record.h"15using namespace llvm;1617void Matcher::anchor() {}1819void Matcher::dump() const { print(errs(), 0); }2021void Matcher::print(raw_ostream &OS, unsigned indent) const {22printImpl(OS, indent);23if (Next)24return Next->print(OS, indent);25}2627void Matcher::printOne(raw_ostream &OS) const { printImpl(OS, 0); }2829/// unlinkNode - Unlink the specified node from this chain. If Other == this,30/// we unlink the next pointer and return it. Otherwise we unlink Other from31/// the list and return this.32Matcher *Matcher::unlinkNode(Matcher *Other) {33if (this == Other)34return takeNext();3536// Scan until we find the predecessor of Other.37Matcher *Cur = this;38for (; Cur && Cur->getNext() != Other; Cur = Cur->getNext())39/*empty*/;4041if (!Cur)42return nullptr;43Cur->takeNext();44Cur->setNext(Other->takeNext());45return this;46}4748/// canMoveBefore - Return true if this matcher is the same as Other, or if49/// we can move this matcher past all of the nodes in-between Other and this50/// node. Other must be equal to or before this.51bool Matcher::canMoveBefore(const Matcher *Other) const {52for (;; Other = Other->getNext()) {53assert(Other && "Other didn't come before 'this'?");54if (this == Other)55return true;5657// We have to be able to move this node across the Other node.58if (!canMoveBeforeNode(Other))59return false;60}61}6263/// canMoveBeforeNode - Return true if it is safe to move the current matcher64/// across the specified one.65bool Matcher::canMoveBeforeNode(const Matcher *Other) const {66// We can move simple predicates before record nodes.67if (isSimplePredicateNode())68return Other->isSimplePredicateOrRecordNode();6970// We can move record nodes across simple predicates.71if (isSimplePredicateOrRecordNode())72return isSimplePredicateNode();7374// We can't move record nodes across each other etc.75return false;76}7778ScopeMatcher::~ScopeMatcher() {79for (Matcher *C : Children)80delete C;81}8283SwitchOpcodeMatcher::~SwitchOpcodeMatcher() {84for (auto &C : Cases)85delete C.second;86}8788SwitchTypeMatcher::~SwitchTypeMatcher() {89for (auto &C : Cases)90delete C.second;91}9293CheckPredicateMatcher::CheckPredicateMatcher(94const TreePredicateFn &pred, const SmallVectorImpl<unsigned> &Ops)95: Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()),96Operands(Ops.begin(), Ops.end()) {}9798TreePredicateFn CheckPredicateMatcher::getPredicate() const {99return TreePredicateFn(Pred);100}101102unsigned CheckPredicateMatcher::getNumOperands() const {103return Operands.size();104}105106unsigned CheckPredicateMatcher::getOperandNo(unsigned i) const {107assert(i < Operands.size());108return Operands[i];109}110111// printImpl methods.112113void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {114OS.indent(indent) << "Scope\n";115for (const Matcher *C : Children) {116if (!C)117OS.indent(indent + 1) << "NULL POINTER\n";118else119C->print(OS, indent + 2);120}121}122123void RecordMatcher::printImpl(raw_ostream &OS, unsigned indent) const {124OS.indent(indent) << "Record\n";125}126127void RecordChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const {128OS.indent(indent) << "RecordChild: " << ChildNo << '\n';129}130131void RecordMemRefMatcher::printImpl(raw_ostream &OS, unsigned indent) const {132OS.indent(indent) << "RecordMemRef\n";133}134135void CaptureGlueInputMatcher::printImpl(raw_ostream &OS,136unsigned indent) const {137OS.indent(indent) << "CaptureGlueInput\n";138}139140void MoveChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const {141OS.indent(indent) << "MoveChild " << ChildNo << '\n';142}143144void MoveSiblingMatcher::printImpl(raw_ostream &OS, unsigned Indent) const {145OS.indent(Indent) << "MoveSibling " << SiblingNo << '\n';146}147148void MoveParentMatcher::printImpl(raw_ostream &OS, unsigned indent) const {149OS.indent(indent) << "MoveParent\n";150}151152void CheckSameMatcher::printImpl(raw_ostream &OS, unsigned indent) const {153OS.indent(indent) << "CheckSame " << MatchNumber << '\n';154}155156void CheckChildSameMatcher::printImpl(raw_ostream &OS, unsigned indent) const {157OS.indent(indent) << "CheckChild" << ChildNo << "Same\n";158}159160void CheckPatternPredicateMatcher::printImpl(raw_ostream &OS,161unsigned indent) const {162OS.indent(indent) << "CheckPatternPredicate " << Predicate << '\n';163}164165void CheckPredicateMatcher::printImpl(raw_ostream &OS, unsigned indent) const {166OS.indent(indent) << "CheckPredicate " << getPredicate().getFnName() << '\n';167}168169void CheckOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {170OS.indent(indent) << "CheckOpcode " << Opcode.getEnumName() << '\n';171}172173void SwitchOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {174OS.indent(indent) << "SwitchOpcode: {\n";175for (const auto &C : Cases) {176OS.indent(indent) << "case " << C.first->getEnumName() << ":\n";177C.second->print(OS, indent + 2);178}179OS.indent(indent) << "}\n";180}181182void CheckTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {183OS.indent(indent) << "CheckType " << getEnumName(Type) << ", ResNo=" << ResNo184<< '\n';185}186187void SwitchTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {188OS.indent(indent) << "SwitchType: {\n";189for (const auto &C : Cases) {190OS.indent(indent) << "case " << getEnumName(C.first) << ":\n";191C.second->print(OS, indent + 2);192}193OS.indent(indent) << "}\n";194}195196void CheckChildTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {197OS.indent(indent) << "CheckChildType " << ChildNo << " " << getEnumName(Type)198<< '\n';199}200201void CheckIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const {202OS.indent(indent) << "CheckInteger " << Value << '\n';203}204205void CheckChildIntegerMatcher::printImpl(raw_ostream &OS,206unsigned indent) const {207OS.indent(indent) << "CheckChildInteger " << ChildNo << " " << Value << '\n';208}209210void CheckCondCodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {211OS.indent(indent) << "CheckCondCode ISD::" << CondCodeName << '\n';212}213214void CheckChild2CondCodeMatcher::printImpl(raw_ostream &OS,215unsigned indent) const {216OS.indent(indent) << "CheckChild2CondCode ISD::" << CondCodeName << '\n';217}218219void CheckValueTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {220OS.indent(indent) << "CheckValueType " << getEnumName(VT) << '\n';221}222223void CheckComplexPatMatcher::printImpl(raw_ostream &OS, unsigned indent) const {224OS.indent(indent) << "CheckComplexPat " << Pattern.getSelectFunc() << '\n';225}226227void CheckAndImmMatcher::printImpl(raw_ostream &OS, unsigned indent) const {228OS.indent(indent) << "CheckAndImm " << Value << '\n';229}230231void CheckOrImmMatcher::printImpl(raw_ostream &OS, unsigned indent) const {232OS.indent(indent) << "CheckOrImm " << Value << '\n';233}234235void CheckFoldableChainNodeMatcher::printImpl(raw_ostream &OS,236unsigned indent) const {237OS.indent(indent) << "CheckFoldableChainNode\n";238}239240void CheckImmAllOnesVMatcher::printImpl(raw_ostream &OS,241unsigned indent) const {242OS.indent(indent) << "CheckAllOnesV\n";243}244245void CheckImmAllZerosVMatcher::printImpl(raw_ostream &OS,246unsigned indent) const {247OS.indent(indent) << "CheckAllZerosV\n";248}249250void EmitIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const {251OS.indent(indent) << "EmitInteger " << Val << " VT=" << getEnumName(VT)252<< '\n';253}254255void EmitStringIntegerMatcher::printImpl(raw_ostream &OS,256unsigned indent) const {257OS.indent(indent) << "EmitStringInteger " << Val << " VT=" << getEnumName(VT)258<< '\n';259}260261void EmitRegisterMatcher::printImpl(raw_ostream &OS, unsigned indent) const {262OS.indent(indent) << "EmitRegister ";263if (Reg)264OS << Reg->getName();265else266OS << "zero_reg";267OS << " VT=" << getEnumName(VT) << '\n';268}269270void EmitConvertToTargetMatcher::printImpl(raw_ostream &OS,271unsigned indent) const {272OS.indent(indent) << "EmitConvertToTarget " << Slot << '\n';273}274275void EmitMergeInputChainsMatcher::printImpl(raw_ostream &OS,276unsigned indent) const {277OS.indent(indent) << "EmitMergeInputChains <todo: args>\n";278}279280void EmitCopyToRegMatcher::printImpl(raw_ostream &OS, unsigned indent) const {281OS.indent(indent) << "EmitCopyToReg <todo: args>\n";282}283284void EmitNodeXFormMatcher::printImpl(raw_ostream &OS, unsigned indent) const {285OS.indent(indent) << "EmitNodeXForm " << NodeXForm->getName()286<< " Slot=" << Slot << '\n';287}288289void EmitNodeMatcherCommon::printImpl(raw_ostream &OS, unsigned indent) const {290OS.indent(indent);291OS << (isa<MorphNodeToMatcher>(this) ? "MorphNodeTo: " : "EmitNode: ")292<< CGI.Namespace << "::" << CGI.TheDef->getName() << ": <todo flags> ";293294for (unsigned i = 0, e = VTs.size(); i != e; ++i)295OS << ' ' << getEnumName(VTs[i]);296OS << '(';297for (unsigned i = 0, e = Operands.size(); i != e; ++i)298OS << Operands[i] << ' ';299OS << ")\n";300}301302void CompleteMatchMatcher::printImpl(raw_ostream &OS, unsigned indent) const {303OS.indent(indent) << "CompleteMatch <todo args>\n";304OS.indent(indent) << "Src = " << Pattern.getSrcPattern() << "\n";305OS.indent(indent) << "Dst = " << Pattern.getDstPattern() << "\n";306}307308bool CheckOpcodeMatcher::isEqualImpl(const Matcher *M) const {309// Note: pointer equality isn't enough here, we have to check the enum names310// to ensure that the nodes are for the same opcode.311return cast<CheckOpcodeMatcher>(M)->Opcode.getEnumName() ==312Opcode.getEnumName();313}314315bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const {316const EmitNodeMatcherCommon *M = cast<EmitNodeMatcherCommon>(m);317return &M->CGI == &CGI && M->VTs == VTs && M->Operands == Operands &&318M->HasChain == HasChain && M->HasInGlue == HasInGlue &&319M->HasOutGlue == HasOutGlue && M->HasMemRefs == HasMemRefs &&320M->NumFixedArityOperands == NumFixedArityOperands;321}322323void EmitNodeMatcher::anchor() {}324325void MorphNodeToMatcher::anchor() {}326327// isContradictoryImpl Implementations.328329static bool TypesAreContradictory(MVT::SimpleValueType T1,330MVT::SimpleValueType T2) {331// If the two types are the same, then they are the same, so they don't332// contradict.333if (T1 == T2)334return false;335336// If either type is about iPtr, then they don't conflict unless the other337// one is not a scalar integer type.338if (T1 == MVT::iPTR)339return !MVT(T2).isInteger() || MVT(T2).isVector();340341if (T2 == MVT::iPTR)342return !MVT(T1).isInteger() || MVT(T1).isVector();343344// Otherwise, they are two different non-iPTR types, they conflict.345return true;346}347348bool CheckOpcodeMatcher::isContradictoryImpl(const Matcher *M) const {349if (const CheckOpcodeMatcher *COM = dyn_cast<CheckOpcodeMatcher>(M)) {350// One node can't have two different opcodes!351// Note: pointer equality isn't enough here, we have to check the enum names352// to ensure that the nodes are for the same opcode.353return COM->getOpcode().getEnumName() != getOpcode().getEnumName();354}355356// If the node has a known type, and if the type we're checking for is357// different, then we know they contradict. For example, a check for358// ISD::STORE will never be true at the same time a check for Type i32 is.359if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M)) {360// If checking for a result the opcode doesn't have, it can't match.361if (CT->getResNo() >= getOpcode().getNumResults())362return true;363364MVT::SimpleValueType NodeType = getOpcode().getKnownType(CT->getResNo());365if (NodeType != MVT::Other)366return TypesAreContradictory(NodeType, CT->getType());367}368369return false;370}371372bool CheckTypeMatcher::isContradictoryImpl(const Matcher *M) const {373if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M))374return TypesAreContradictory(getType(), CT->getType());375return false;376}377378bool CheckChildTypeMatcher::isContradictoryImpl(const Matcher *M) const {379if (const CheckChildTypeMatcher *CC = dyn_cast<CheckChildTypeMatcher>(M)) {380// If the two checks are about different nodes, we don't know if they381// conflict!382if (CC->getChildNo() != getChildNo())383return false;384385return TypesAreContradictory(getType(), CC->getType());386}387return false;388}389390bool CheckIntegerMatcher::isContradictoryImpl(const Matcher *M) const {391if (const CheckIntegerMatcher *CIM = dyn_cast<CheckIntegerMatcher>(M))392return CIM->getValue() != getValue();393return false;394}395396bool CheckChildIntegerMatcher::isContradictoryImpl(const Matcher *M) const {397if (const CheckChildIntegerMatcher *CCIM =398dyn_cast<CheckChildIntegerMatcher>(M)) {399// If the two checks are about different nodes, we don't know if they400// conflict!401if (CCIM->getChildNo() != getChildNo())402return false;403404return CCIM->getValue() != getValue();405}406return false;407}408409bool CheckValueTypeMatcher::isContradictoryImpl(const Matcher *M) const {410if (const CheckValueTypeMatcher *CVT = dyn_cast<CheckValueTypeMatcher>(M))411return CVT->getVT() != getVT();412return false;413}414415bool CheckImmAllOnesVMatcher::isContradictoryImpl(const Matcher *M) const {416// AllZeros is contradictory.417return isa<CheckImmAllZerosVMatcher>(M);418}419420bool CheckImmAllZerosVMatcher::isContradictoryImpl(const Matcher *M) const {421// AllOnes is contradictory.422return isa<CheckImmAllOnesVMatcher>(M);423}424425bool CheckCondCodeMatcher::isContradictoryImpl(const Matcher *M) const {426if (const auto *CCCM = dyn_cast<CheckCondCodeMatcher>(M))427return CCCM->getCondCodeName() != getCondCodeName();428return false;429}430431bool CheckChild2CondCodeMatcher::isContradictoryImpl(const Matcher *M) const {432if (const auto *CCCCM = dyn_cast<CheckChild2CondCodeMatcher>(M))433return CCCCM->getCondCodeName() != getCondCodeName();434return false;435}436437438