1cde4d5a6SJacques Pienaar //===- Pattern.cpp - Pattern wrapper class --------------------------------===// 2eb753f4aSLei Zhang // 330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information. 556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6eb753f4aSLei Zhang // 756222a06SMehdi Amini //===----------------------------------------------------------------------===// 8eb753f4aSLei Zhang // 9eb753f4aSLei Zhang // Pattern wrapper class to simplify using TableGen Record defining a MLIR 10eb753f4aSLei Zhang // Pattern. 11eb753f4aSLei Zhang // 12eb753f4aSLei Zhang //===----------------------------------------------------------------------===// 13eb753f4aSLei Zhang 14eb753f4aSLei Zhang #include "mlir/TableGen/Pattern.h" 15b12a7c88SMehdi Amini #include "llvm/ADT/StringExtras.h" 16eb753f4aSLei Zhang #include "llvm/ADT/Twine.h" 171358df19SLei Zhang #include "llvm/Support/Debug.h" 1804b6d2f3SLei Zhang #include "llvm/Support/FormatVariadic.h" 198f5fa566SLei Zhang #include "llvm/TableGen/Error.h" 20eb753f4aSLei Zhang #include "llvm/TableGen/Record.h" 21eb753f4aSLei Zhang 221358df19SLei Zhang #define DEBUG_TYPE "mlir-tblgen-pattern" 231358df19SLei Zhang 24eb753f4aSLei Zhang using namespace mlir; 2512d16de5SRahul Joshi using namespace tblgen; 26eb753f4aSLei Zhang 270ea6154bSJacques Pienaar using llvm::formatv; 28eb753f4aSLei Zhang 29ac68637bSLei Zhang //===----------------------------------------------------------------------===// 30ac68637bSLei Zhang // DagLeaf 31ac68637bSLei Zhang //===----------------------------------------------------------------------===// 32ac68637bSLei Zhang 3312d16de5SRahul Joshi bool DagLeaf::isUnspecified() const { 34b9e38a79SLei Zhang return dyn_cast_or_null<llvm::UnsetInit>(def); 35e0774c00SLei Zhang } 36e0774c00SLei Zhang 3712d16de5SRahul Joshi bool DagLeaf::isOperandMatcher() const { 38e0774c00SLei Zhang // Operand matchers specify a type constraint. 39b9e38a79SLei Zhang return isSubClassOf("TypeConstraint"); 40e0774c00SLei Zhang } 41e0774c00SLei Zhang 4212d16de5SRahul Joshi bool DagLeaf::isAttrMatcher() const { 43c52a8127SFeng Liu // Attribute matchers specify an attribute constraint. 44b9e38a79SLei Zhang return isSubClassOf("AttrConstraint"); 45e0774c00SLei Zhang } 46e0774c00SLei Zhang 4712d16de5SRahul Joshi bool DagLeaf::isNativeCodeCall() const { 48d0e2019dSLei Zhang return isSubClassOf("NativeCodeCall"); 49e0774c00SLei Zhang } 50e0774c00SLei Zhang 5112d16de5SRahul Joshi bool DagLeaf::isConstantAttr() const { return isSubClassOf("ConstantAttr"); } 52b9e38a79SLei Zhang 5312d16de5SRahul Joshi bool DagLeaf::isEnumAttrCase() const { 549dd182e0SLei Zhang return isSubClassOf("EnumAttrCaseInfo"); 55e0774c00SLei Zhang } 56e0774c00SLei Zhang 57cb8c30d3SMogball bool DagLeaf::isStringAttr() const { return isa<llvm::StringInit>(def); } 58d6b32e39SJacques Pienaar 5912d16de5SRahul Joshi Constraint DagLeaf::getAsConstraint() const { 608f5fa566SLei Zhang assert((isOperandMatcher() || isAttrMatcher()) && 618f5fa566SLei Zhang "the DAG leaf must be operand or attribute"); 628f5fa566SLei Zhang return Constraint(cast<llvm::DefInit>(def)->getDef()); 63e0774c00SLei Zhang } 64e0774c00SLei Zhang 6512d16de5SRahul Joshi ConstantAttr DagLeaf::getAsConstantAttr() const { 66e0774c00SLei Zhang assert(isConstantAttr() && "the DAG leaf must be constant attribute"); 67e0774c00SLei Zhang return ConstantAttr(cast<llvm::DefInit>(def)); 68e0774c00SLei Zhang } 69e0774c00SLei Zhang 7012d16de5SRahul Joshi EnumAttrCase DagLeaf::getAsEnumAttrCase() const { 71b9e38a79SLei Zhang assert(isEnumAttrCase() && "the DAG leaf must be an enum attribute case"); 72b9e38a79SLei Zhang return EnumAttrCase(cast<llvm::DefInit>(def)); 73b9e38a79SLei Zhang } 74b9e38a79SLei Zhang 7512d16de5SRahul Joshi std::string DagLeaf::getConditionTemplate() const { 768f5fa566SLei Zhang return getAsConstraint().getConditionTemplate(); 77e0774c00SLei Zhang } 78e0774c00SLei Zhang 7912d16de5SRahul Joshi llvm::StringRef DagLeaf::getNativeCodeTemplate() const { 80d0e2019dSLei Zhang assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall"); 81d0e2019dSLei Zhang return cast<llvm::DefInit>(def)->getDef()->getValueAsString("expression"); 82eb753f4aSLei Zhang } 83eb753f4aSLei Zhang 84d7314b3cSChia-hung Duan int DagLeaf::getNumReturnsOfNativeCode() const { 85d7314b3cSChia-hung Duan assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall"); 86d7314b3cSChia-hung Duan return cast<llvm::DefInit>(def)->getDef()->getValueAsInt("numReturns"); 87d7314b3cSChia-hung Duan } 88d7314b3cSChia-hung Duan 8912d16de5SRahul Joshi std::string DagLeaf::getStringAttr() const { 90d6b32e39SJacques Pienaar assert(isStringAttr() && "the DAG leaf must be string attribute"); 91d6b32e39SJacques Pienaar return def->getAsUnquotedString(); 92d6b32e39SJacques Pienaar } 9312d16de5SRahul Joshi bool DagLeaf::isSubClassOf(StringRef superclass) const { 94b9e38a79SLei Zhang if (auto *defInit = dyn_cast_or_null<llvm::DefInit>(def)) 95b9e38a79SLei Zhang return defInit->getDef()->isSubClassOf(superclass); 96b9e38a79SLei Zhang return false; 97b9e38a79SLei Zhang } 98b9e38a79SLei Zhang 9912d16de5SRahul Joshi void DagLeaf::print(raw_ostream &os) const { 1001358df19SLei Zhang if (def) 1011358df19SLei Zhang def->print(os); 1021358df19SLei Zhang } 1031358df19SLei Zhang 104ac68637bSLei Zhang //===----------------------------------------------------------------------===// 105ac68637bSLei Zhang // DagNode 106ac68637bSLei Zhang //===----------------------------------------------------------------------===// 107ac68637bSLei Zhang 10812d16de5SRahul Joshi bool DagNode::isNativeCodeCall() const { 109d0e2019dSLei Zhang if (auto *defInit = dyn_cast_or_null<llvm::DefInit>(node->getOperator())) 110d0e2019dSLei Zhang return defInit->getDef()->isSubClassOf("NativeCodeCall"); 111c52a8127SFeng Liu return false; 112c52a8127SFeng Liu } 113c52a8127SFeng Liu 11412d16de5SRahul Joshi bool DagNode::isOperation() const { 115cb8c30d3SMogball return !isNativeCodeCall() && !isReplaceWithValue() && 116cb8c30d3SMogball !isLocationDirective() && !isReturnTypeDirective(); 117647f8cabSRiver Riddle } 118647f8cabSRiver Riddle 11912d16de5SRahul Joshi llvm::StringRef DagNode::getNativeCodeTemplate() const { 120d0e2019dSLei Zhang assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall"); 121c52a8127SFeng Liu return cast<llvm::DefInit>(node->getOperator()) 122c52a8127SFeng Liu ->getDef() 123d0e2019dSLei Zhang ->getValueAsString("expression"); 124c52a8127SFeng Liu } 125c52a8127SFeng Liu 126d7314b3cSChia-hung Duan int DagNode::getNumReturnsOfNativeCode() const { 127d7314b3cSChia-hung Duan assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall"); 128d7314b3cSChia-hung Duan return cast<llvm::DefInit>(node->getOperator()) 129d7314b3cSChia-hung Duan ->getDef() 130d7314b3cSChia-hung Duan ->getValueAsInt("numReturns"); 131d7314b3cSChia-hung Duan } 132d7314b3cSChia-hung Duan 13312d16de5SRahul Joshi llvm::StringRef DagNode::getSymbol() const { return node->getNameStr(); } 134388fb375SJacques Pienaar 13512d16de5SRahul Joshi Operator &DagNode::getDialectOp(RecordOperatorMap *mapper) const { 136eb753f4aSLei Zhang llvm::Record *opDef = cast<llvm::DefInit>(node->getOperator())->getDef(); 1372dc6d205SLei Zhang auto it = mapper->find(opDef); 1382dc6d205SLei Zhang if (it != mapper->end()) 1392dc6d205SLei Zhang return *it->second; 14079f53b0cSJacques Pienaar return *mapper->try_emplace(opDef, std::make_unique<Operator>(opDef)) 1412dc6d205SLei Zhang .first->second; 142eb753f4aSLei Zhang } 143eb753f4aSLei Zhang 14412d16de5SRahul Joshi int DagNode::getNumOps() const { 1452fe8ae4fSJacques Pienaar int count = isReplaceWithValue() ? 0 : 1; 1462fe8ae4fSJacques Pienaar for (int i = 0, e = getNumArgs(); i != e; ++i) { 147eb753f4aSLei Zhang if (auto child = getArgAsNestedDag(i)) 148eb753f4aSLei Zhang count += child.getNumOps(); 149eb753f4aSLei Zhang } 150eb753f4aSLei Zhang return count; 151eb753f4aSLei Zhang } 152eb753f4aSLei Zhang 15312d16de5SRahul Joshi int DagNode::getNumArgs() const { return node->getNumArgs(); } 154eb753f4aSLei Zhang 15512d16de5SRahul Joshi bool DagNode::isNestedDagArg(unsigned index) const { 156eb753f4aSLei Zhang return isa<llvm::DagInit>(node->getArg(index)); 157eb753f4aSLei Zhang } 158eb753f4aSLei Zhang 15912d16de5SRahul Joshi DagNode DagNode::getArgAsNestedDag(unsigned index) const { 160eb753f4aSLei Zhang return DagNode(dyn_cast_or_null<llvm::DagInit>(node->getArg(index))); 161eb753f4aSLei Zhang } 162eb753f4aSLei Zhang 16312d16de5SRahul Joshi DagLeaf DagNode::getArgAsLeaf(unsigned index) const { 164e0774c00SLei Zhang assert(!isNestedDagArg(index)); 165e0774c00SLei Zhang return DagLeaf(node->getArg(index)); 166eb753f4aSLei Zhang } 167eb753f4aSLei Zhang 16812d16de5SRahul Joshi StringRef DagNode::getArgName(unsigned index) const { 169eb753f4aSLei Zhang return node->getArgNameStr(index); 170eb753f4aSLei Zhang } 171eb753f4aSLei Zhang 17212d16de5SRahul Joshi bool DagNode::isReplaceWithValue() const { 173eb753f4aSLei Zhang auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef(); 174eb753f4aSLei Zhang return dagOpDef->getName() == "replaceWithValue"; 175eb753f4aSLei Zhang } 176eb753f4aSLei Zhang 17712d16de5SRahul Joshi bool DagNode::isLocationDirective() const { 1783f7439b2SJacques Pienaar auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef(); 1793f7439b2SJacques Pienaar return dagOpDef->getName() == "location"; 1803f7439b2SJacques Pienaar } 1813f7439b2SJacques Pienaar 182cb8c30d3SMogball bool DagNode::isReturnTypeDirective() const { 183cb8c30d3SMogball auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef(); 184cb8c30d3SMogball return dagOpDef->getName() == "returnType"; 185cb8c30d3SMogball } 186cb8c30d3SMogball 18712d16de5SRahul Joshi void DagNode::print(raw_ostream &os) const { 1881358df19SLei Zhang if (node) 1891358df19SLei Zhang node->print(os); 1901358df19SLei Zhang } 1911358df19SLei Zhang 192ac68637bSLei Zhang //===----------------------------------------------------------------------===// 193ac68637bSLei Zhang // SymbolInfoMap 194ac68637bSLei Zhang //===----------------------------------------------------------------------===// 195ac68637bSLei Zhang 19612d16de5SRahul Joshi StringRef SymbolInfoMap::getValuePackName(StringRef symbol, int *index) { 197ac68637bSLei Zhang StringRef name, indexStr; 198ac68637bSLei Zhang int idx = -1; 199ac68637bSLei Zhang std::tie(name, indexStr) = symbol.rsplit("__"); 200ac68637bSLei Zhang 201ac68637bSLei Zhang if (indexStr.consumeInteger(10, idx)) { 202ac68637bSLei Zhang // The second part is not an index; we return the whole symbol as-is. 203ac68637bSLei Zhang return symbol; 204eb753f4aSLei Zhang } 205ac68637bSLei Zhang if (index) { 206ac68637bSLei Zhang *index = idx; 207ac68637bSLei Zhang } 208ac68637bSLei Zhang return name; 209ac68637bSLei Zhang } 210ac68637bSLei Zhang 21112d16de5SRahul Joshi SymbolInfoMap::SymbolInfo::SymbolInfo(const Operator *op, SymbolInfo::Kind kind, 212d7314b3cSChia-hung Duan Optional<DagAndConstant> dagAndConstant) 213d7314b3cSChia-hung Duan : op(op), kind(kind), dagAndConstant(dagAndConstant) {} 214ac68637bSLei Zhang 21512d16de5SRahul Joshi int SymbolInfoMap::SymbolInfo::getStaticValueCount() const { 216ac68637bSLei Zhang switch (kind) { 217ac68637bSLei Zhang case Kind::Attr: 218ac68637bSLei Zhang case Kind::Operand: 219ac68637bSLei Zhang case Kind::Value: 220ac68637bSLei Zhang return 1; 221ac68637bSLei Zhang case Kind::Result: 222ac68637bSLei Zhang return op->getNumResults(); 223d7314b3cSChia-hung Duan case Kind::MultipleValues: 224d7314b3cSChia-hung Duan return getSize(); 225ac68637bSLei Zhang } 22612ff145eSjpienaar llvm_unreachable("unknown kind"); 227ac68637bSLei Zhang } 228ac68637bSLei Zhang 229008c0ea6Srdzhabarov std::string SymbolInfoMap::SymbolInfo::getVarName(StringRef name) const { 230008c0ea6Srdzhabarov return alternativeName.hasValue() ? alternativeName.getValue() : name.str(); 231008c0ea6Srdzhabarov } 232008c0ea6Srdzhabarov 233*bb250606SChia-hung Duan std::string SymbolInfoMap::SymbolInfo::getVarTypeStr(StringRef name) const { 234*bb250606SChia-hung Duan LLVM_DEBUG(llvm::dbgs() << "getVarTypeStr for '" << name << "': "); 235ac68637bSLei Zhang switch (kind) { 236ac68637bSLei Zhang case Kind::Attr: { 237*bb250606SChia-hung Duan if (op) 238*bb250606SChia-hung Duan return op->getArg(getArgIndex()) 239b4001ae8SChia-hung Duan .get<NamedAttribute *>() 240*bb250606SChia-hung Duan ->attr.getStorageType() 241*bb250606SChia-hung Duan .str(); 2422bf423b0SRob Suderman // TODO(suderman): Use a more exact type when available. 243*bb250606SChia-hung Duan return "Attribute"; 2442bf423b0SRob Suderman } 24531cfee60SLei Zhang case Kind::Operand: { 24631cfee60SLei Zhang // Use operand range for captured operands (to support potential variadic 24731cfee60SLei Zhang // operands). 248*bb250606SChia-hung Duan return "::mlir::Operation::operand_range"; 24931cfee60SLei Zhang } 250ac68637bSLei Zhang case Kind::Value: { 251*bb250606SChia-hung Duan return "::mlir::Value"; 252ac68637bSLei Zhang } 253d7314b3cSChia-hung Duan case Kind::MultipleValues: { 254*bb250606SChia-hung Duan return "::mlir::ValueRange"; 255d7314b3cSChia-hung Duan } 256ac68637bSLei Zhang case Kind::Result: { 25731cfee60SLei Zhang // Use the op itself for captured results. 258*bb250606SChia-hung Duan return op->getQualCppClassName(); 259ac68637bSLei Zhang } 260ac68637bSLei Zhang } 26112ff145eSjpienaar llvm_unreachable("unknown kind"); 262ac68637bSLei Zhang } 263ac68637bSLei Zhang 264*bb250606SChia-hung Duan std::string SymbolInfoMap::SymbolInfo::getVarDecl(StringRef name) const { 265*bb250606SChia-hung Duan LLVM_DEBUG(llvm::dbgs() << "getVarDecl for '" << name << "': "); 266*bb250606SChia-hung Duan std::string varInit = kind == Kind::Operand ? "(op0->getOperands())" : ""; 267*bb250606SChia-hung Duan return std::string( 268*bb250606SChia-hung Duan formatv("{0} {1}{2};\n", getVarTypeStr(name), getVarName(name), varInit)); 269*bb250606SChia-hung Duan } 270*bb250606SChia-hung Duan 271*bb250606SChia-hung Duan std::string SymbolInfoMap::SymbolInfo::getArgDecl(StringRef name) const { 272*bb250606SChia-hung Duan LLVM_DEBUG(llvm::dbgs() << "getArgDecl for '" << name << "': "); 273*bb250606SChia-hung Duan return std::string( 274*bb250606SChia-hung Duan formatv("{0} &{1}", getVarTypeStr(name), getVarName(name))); 275*bb250606SChia-hung Duan } 276*bb250606SChia-hung Duan 27712d16de5SRahul Joshi std::string SymbolInfoMap::SymbolInfo::getValueAndRangeUse( 27831cfee60SLei Zhang StringRef name, int index, const char *fmt, const char *separator) const { 2791358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "getValueAndRangeUse for '" << name << "': "); 28031cfee60SLei Zhang switch (kind) { 28131cfee60SLei Zhang case Kind::Attr: { 28231cfee60SLei Zhang assert(index < 0); 2831358df19SLei Zhang auto repl = formatv(fmt, name); 2841358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (Attr)\n"); 285adcd0268SBenjamin Kramer return std::string(repl); 28631cfee60SLei Zhang } 28731cfee60SLei Zhang case Kind::Operand: { 28831cfee60SLei Zhang assert(index < 0); 289d7314b3cSChia-hung Duan auto *operand = op->getArg(getArgIndex()).get<NamedTypeConstraint *>(); 29031cfee60SLei Zhang // If this operand is variadic, then return a range. Otherwise, return the 29131cfee60SLei Zhang // value itself. 292aba1acc8SRiver Riddle if (operand->isVariableLength()) { 2931358df19SLei Zhang auto repl = formatv(fmt, name); 2941358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (VariadicOperand)\n"); 295adcd0268SBenjamin Kramer return std::string(repl); 29631cfee60SLei Zhang } 2971358df19SLei Zhang auto repl = formatv(fmt, formatv("(*{0}.begin())", name)); 2981358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (SingleOperand)\n"); 299adcd0268SBenjamin Kramer return std::string(repl); 30031cfee60SLei Zhang } 30131cfee60SLei Zhang case Kind::Result: { 30231cfee60SLei Zhang // If `index` is greater than zero, then we are referencing a specific 30331cfee60SLei Zhang // result of a multi-result op. The result can still be variadic. 30431cfee60SLei Zhang if (index >= 0) { 305adcd0268SBenjamin Kramer std::string v = 306adcd0268SBenjamin Kramer std::string(formatv("{0}.getODSResults({1})", name, index)); 30731cfee60SLei Zhang if (!op->getResult(index).isVariadic()) 308adcd0268SBenjamin Kramer v = std::string(formatv("(*{0}.begin())", v)); 3091358df19SLei Zhang auto repl = formatv(fmt, v); 3101358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (SingleResult)\n"); 311adcd0268SBenjamin Kramer return std::string(repl); 31231cfee60SLei Zhang } 31331cfee60SLei Zhang 31423d21af6SLei Zhang // If this op has no result at all but still we bind a symbol to it, it 31523d21af6SLei Zhang // means we want to capture the op itself. 31623d21af6SLei Zhang if (op->getNumResults() == 0) { 31723d21af6SLei Zhang LLVM_DEBUG(llvm::dbgs() << name << " (Op)\n"); 318adcd0268SBenjamin Kramer return std::string(name); 31923d21af6SLei Zhang } 32023d21af6SLei Zhang 32131cfee60SLei Zhang // We are referencing all results of the multi-result op. A specific result 32231cfee60SLei Zhang // can either be a value or a range. Then join them with `separator`. 32331cfee60SLei Zhang SmallVector<std::string, 4> values; 32431cfee60SLei Zhang values.reserve(op->getNumResults()); 32531cfee60SLei Zhang 32631cfee60SLei Zhang for (int i = 0, e = op->getNumResults(); i < e; ++i) { 327adcd0268SBenjamin Kramer std::string v = std::string(formatv("{0}.getODSResults({1})", name, i)); 32831cfee60SLei Zhang if (!op->getResult(i).isVariadic()) { 329adcd0268SBenjamin Kramer v = std::string(formatv("(*{0}.begin())", v)); 33031cfee60SLei Zhang } 331adcd0268SBenjamin Kramer values.push_back(std::string(formatv(fmt, v))); 33231cfee60SLei Zhang } 3331358df19SLei Zhang auto repl = llvm::join(values, separator); 3341358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (VariadicResult)\n"); 3351358df19SLei Zhang return repl; 33631cfee60SLei Zhang } 33731cfee60SLei Zhang case Kind::Value: { 33831cfee60SLei Zhang assert(index < 0); 33931cfee60SLei Zhang assert(op == nullptr); 3401358df19SLei Zhang auto repl = formatv(fmt, name); 3411358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (Value)\n"); 342adcd0268SBenjamin Kramer return std::string(repl); 34331cfee60SLei Zhang } 344d7314b3cSChia-hung Duan case Kind::MultipleValues: { 345d7314b3cSChia-hung Duan assert(op == nullptr); 346d7314b3cSChia-hung Duan assert(index < getSize()); 347d7314b3cSChia-hung Duan if (index >= 0) { 348d7314b3cSChia-hung Duan std::string repl = 349d7314b3cSChia-hung Duan formatv(fmt, std::string(formatv("{0}[{1}]", name, index))); 350d7314b3cSChia-hung Duan LLVM_DEBUG(llvm::dbgs() << repl << " (MultipleValues)\n"); 351d7314b3cSChia-hung Duan return repl; 352d7314b3cSChia-hung Duan } 353d7314b3cSChia-hung Duan // If it doesn't specify certain element, unpack them all. 354d7314b3cSChia-hung Duan auto repl = 355d7314b3cSChia-hung Duan formatv(fmt, std::string(formatv("{0}.begin(), {0}.end()", name))); 356d7314b3cSChia-hung Duan LLVM_DEBUG(llvm::dbgs() << repl << " (MultipleValues)\n"); 357d7314b3cSChia-hung Duan return std::string(repl); 358d7314b3cSChia-hung Duan } 35931cfee60SLei Zhang } 36094298ceaSLei Zhang llvm_unreachable("unknown kind"); 36131cfee60SLei Zhang } 36231cfee60SLei Zhang 36312d16de5SRahul Joshi std::string SymbolInfoMap::SymbolInfo::getAllRangeUse( 36431cfee60SLei Zhang StringRef name, int index, const char *fmt, const char *separator) const { 3651358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "getAllRangeUse for '" << name << "': "); 366ac68637bSLei Zhang switch (kind) { 367ac68637bSLei Zhang case Kind::Attr: 368ac68637bSLei Zhang case Kind::Operand: { 369ac68637bSLei Zhang assert(index < 0 && "only allowed for symbol bound to result"); 3701358df19SLei Zhang auto repl = formatv(fmt, name); 3711358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (Operand/Attr)\n"); 372adcd0268SBenjamin Kramer return std::string(repl); 373ac68637bSLei Zhang } 374ac68637bSLei Zhang case Kind::Result: { 375ac68637bSLei Zhang if (index >= 0) { 3761358df19SLei Zhang auto repl = formatv(fmt, formatv("{0}.getODSResults({1})", name, index)); 3771358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (SingleResult)\n"); 378adcd0268SBenjamin Kramer return std::string(repl); 379ac68637bSLei Zhang } 380ac68637bSLei Zhang 38131cfee60SLei Zhang // We are referencing all results of the multi-result op. Each result should 38231cfee60SLei Zhang // have a value range, and then join them with `separator`. 383ac68637bSLei Zhang SmallVector<std::string, 4> values; 38431cfee60SLei Zhang values.reserve(op->getNumResults()); 38531cfee60SLei Zhang 386ac68637bSLei Zhang for (int i = 0, e = op->getNumResults(); i < e; ++i) { 387adcd0268SBenjamin Kramer values.push_back(std::string( 388adcd0268SBenjamin Kramer formatv(fmt, formatv("{0}.getODSResults({1})", name, i)))); 389ac68637bSLei Zhang } 3901358df19SLei Zhang auto repl = llvm::join(values, separator); 3911358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (VariadicResult)\n"); 3921358df19SLei Zhang return repl; 393ac68637bSLei Zhang } 394ac68637bSLei Zhang case Kind::Value: { 395ac68637bSLei Zhang assert(index < 0 && "only allowed for symbol bound to result"); 396ac68637bSLei Zhang assert(op == nullptr); 39760f1d263SLei Zhang auto repl = formatv(fmt, formatv("{{{0}}", name)); 3981358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (Value)\n"); 399adcd0268SBenjamin Kramer return std::string(repl); 400ac68637bSLei Zhang } 401d7314b3cSChia-hung Duan case Kind::MultipleValues: { 402d7314b3cSChia-hung Duan assert(op == nullptr); 403d7314b3cSChia-hung Duan assert(index < getSize()); 404d7314b3cSChia-hung Duan if (index >= 0) { 405d7314b3cSChia-hung Duan std::string repl = 406d7314b3cSChia-hung Duan formatv(fmt, std::string(formatv("{0}[{1}]", name, index))); 407d7314b3cSChia-hung Duan LLVM_DEBUG(llvm::dbgs() << repl << " (MultipleValues)\n"); 408d7314b3cSChia-hung Duan return repl; 409d7314b3cSChia-hung Duan } 410d7314b3cSChia-hung Duan auto repl = 411d7314b3cSChia-hung Duan formatv(fmt, std::string(formatv("{0}.begin(), {0}.end()", name))); 412d7314b3cSChia-hung Duan LLVM_DEBUG(llvm::dbgs() << repl << " (MultipleValues)\n"); 413d7314b3cSChia-hung Duan return std::string(repl); 414d7314b3cSChia-hung Duan } 415ac68637bSLei Zhang } 41612ff145eSjpienaar llvm_unreachable("unknown kind"); 417ac68637bSLei Zhang } 418ac68637bSLei Zhang 419b4001ae8SChia-hung Duan bool SymbolInfoMap::bindOpArgument(DagNode node, StringRef symbol, 420b4001ae8SChia-hung Duan const Operator &op, int argIndex) { 421ac68637bSLei Zhang StringRef name = getValuePackName(symbol); 422ac68637bSLei Zhang if (name != symbol) { 423ac68637bSLei Zhang auto error = formatv( 424ac68637bSLei Zhang "symbol '{0}' with trailing index cannot bind to op argument", symbol); 425ac68637bSLei Zhang PrintFatalError(loc, error); 426ac68637bSLei Zhang } 427ac68637bSLei Zhang 428ac68637bSLei Zhang auto symInfo = op.getArg(argIndex).is<NamedAttribute *>() 429ac68637bSLei Zhang ? SymbolInfo::getAttr(&op, argIndex) 430b4001ae8SChia-hung Duan : SymbolInfo::getOperand(node, &op, argIndex); 431ac68637bSLei Zhang 432008c0ea6Srdzhabarov std::string key = symbol.str(); 433008c0ea6Srdzhabarov if (symbolInfoMap.count(key)) { 434008c0ea6Srdzhabarov // Only non unique name for the operand is supported. 435008c0ea6Srdzhabarov if (symInfo.kind != SymbolInfo::Kind::Operand) { 436008c0ea6Srdzhabarov return false; 437008c0ea6Srdzhabarov } 438008c0ea6Srdzhabarov 439008c0ea6Srdzhabarov // Cannot add new operand if there is already non operand with the same 440008c0ea6Srdzhabarov // name. 441008c0ea6Srdzhabarov if (symbolInfoMap.find(key)->second.kind != SymbolInfo::Kind::Operand) { 442008c0ea6Srdzhabarov return false; 443008c0ea6Srdzhabarov } 444008c0ea6Srdzhabarov } 445008c0ea6Srdzhabarov 446008c0ea6Srdzhabarov symbolInfoMap.emplace(key, symInfo); 447008c0ea6Srdzhabarov return true; 448ac68637bSLei Zhang } 449ac68637bSLei Zhang 45012d16de5SRahul Joshi bool SymbolInfoMap::bindOpResult(StringRef symbol, const Operator &op) { 451008c0ea6Srdzhabarov std::string name = getValuePackName(symbol).str(); 452008c0ea6Srdzhabarov auto inserted = symbolInfoMap.emplace(name, SymbolInfo::getResult(&op)); 453008c0ea6Srdzhabarov 454008c0ea6Srdzhabarov return symbolInfoMap.count(inserted->first) == 1; 455ac68637bSLei Zhang } 456ac68637bSLei Zhang 457d7314b3cSChia-hung Duan bool SymbolInfoMap::bindValues(StringRef symbol, int numValues) { 458d7314b3cSChia-hung Duan std::string name = getValuePackName(symbol).str(); 459d7314b3cSChia-hung Duan if (numValues > 1) 460d7314b3cSChia-hung Duan return bindMultipleValues(name, numValues); 461d7314b3cSChia-hung Duan return bindValue(name); 462d7314b3cSChia-hung Duan } 463d7314b3cSChia-hung Duan 46412d16de5SRahul Joshi bool SymbolInfoMap::bindValue(StringRef symbol) { 465008c0ea6Srdzhabarov auto inserted = symbolInfoMap.emplace(symbol.str(), SymbolInfo::getValue()); 466008c0ea6Srdzhabarov return symbolInfoMap.count(inserted->first) == 1; 467ac68637bSLei Zhang } 468ac68637bSLei Zhang 469d7314b3cSChia-hung Duan bool SymbolInfoMap::bindMultipleValues(StringRef symbol, int numValues) { 470d7314b3cSChia-hung Duan std::string name = getValuePackName(symbol).str(); 471d7314b3cSChia-hung Duan auto inserted = 472d7314b3cSChia-hung Duan symbolInfoMap.emplace(name, SymbolInfo::getMultipleValues(numValues)); 473d7314b3cSChia-hung Duan return symbolInfoMap.count(inserted->first) == 1; 474d7314b3cSChia-hung Duan } 475d7314b3cSChia-hung Duan 4762bf423b0SRob Suderman bool SymbolInfoMap::bindAttr(StringRef symbol) { 477ad1fe396SRob Suderman auto inserted = symbolInfoMap.emplace(symbol.str(), SymbolInfo::getAttr()); 4782bf423b0SRob Suderman return symbolInfoMap.count(inserted->first) == 1; 4792bf423b0SRob Suderman } 4802bf423b0SRob Suderman 48112d16de5SRahul Joshi bool SymbolInfoMap::contains(StringRef symbol) const { 482ac68637bSLei Zhang return find(symbol) != symbolInfoMap.end(); 483ac68637bSLei Zhang } 484ac68637bSLei Zhang 48512d16de5SRahul Joshi SymbolInfoMap::const_iterator SymbolInfoMap::find(StringRef key) const { 486008c0ea6Srdzhabarov std::string name = getValuePackName(key).str(); 487008c0ea6Srdzhabarov 488ac68637bSLei Zhang return symbolInfoMap.find(name); 489ac68637bSLei Zhang } 490ac68637bSLei Zhang 491008c0ea6Srdzhabarov SymbolInfoMap::const_iterator 492b4001ae8SChia-hung Duan SymbolInfoMap::findBoundSymbol(StringRef key, DagNode node, const Operator &op, 493008c0ea6Srdzhabarov int argIndex) const { 494*bb250606SChia-hung Duan return findBoundSymbol(key, SymbolInfo::getOperand(node, &op, argIndex)); 495*bb250606SChia-hung Duan } 496*bb250606SChia-hung Duan 497*bb250606SChia-hung Duan SymbolInfoMap::const_iterator 498*bb250606SChia-hung Duan SymbolInfoMap::findBoundSymbol(StringRef key, SymbolInfo symbolInfo) const { 499008c0ea6Srdzhabarov std::string name = getValuePackName(key).str(); 500008c0ea6Srdzhabarov auto range = symbolInfoMap.equal_range(name); 501008c0ea6Srdzhabarov 502d7314b3cSChia-hung Duan for (auto it = range.first; it != range.second; ++it) 503d7314b3cSChia-hung Duan if (it->second.dagAndConstant == symbolInfo.dagAndConstant) 504008c0ea6Srdzhabarov return it; 505008c0ea6Srdzhabarov 506008c0ea6Srdzhabarov return symbolInfoMap.end(); 507008c0ea6Srdzhabarov } 508008c0ea6Srdzhabarov 509008c0ea6Srdzhabarov std::pair<SymbolInfoMap::iterator, SymbolInfoMap::iterator> 510008c0ea6Srdzhabarov SymbolInfoMap::getRangeOfEqualElements(StringRef key) { 511008c0ea6Srdzhabarov std::string name = getValuePackName(key).str(); 512008c0ea6Srdzhabarov 513008c0ea6Srdzhabarov return symbolInfoMap.equal_range(name); 514008c0ea6Srdzhabarov } 515008c0ea6Srdzhabarov 516008c0ea6Srdzhabarov int SymbolInfoMap::count(StringRef key) const { 517008c0ea6Srdzhabarov std::string name = getValuePackName(key).str(); 518008c0ea6Srdzhabarov return symbolInfoMap.count(name); 519008c0ea6Srdzhabarov } 520008c0ea6Srdzhabarov 52112d16de5SRahul Joshi int SymbolInfoMap::getStaticValueCount(StringRef symbol) const { 522ac68637bSLei Zhang StringRef name = getValuePackName(symbol); 523ac68637bSLei Zhang if (name != symbol) { 524ac68637bSLei Zhang // If there is a trailing index inside symbol, it references just one 525ac68637bSLei Zhang // static value. 526ac68637bSLei Zhang return 1; 527ac68637bSLei Zhang } 528ac68637bSLei Zhang // Otherwise, find how many it represents by querying the symbol's info. 529008c0ea6Srdzhabarov return find(name)->second.getStaticValueCount(); 530ac68637bSLei Zhang } 531ac68637bSLei Zhang 53212d16de5SRahul Joshi std::string SymbolInfoMap::getValueAndRangeUse(StringRef symbol, 53312d16de5SRahul Joshi const char *fmt, 53431cfee60SLei Zhang const char *separator) const { 535ac68637bSLei Zhang int index = -1; 536ac68637bSLei Zhang StringRef name = getValuePackName(symbol, &index); 537ac68637bSLei Zhang 538008c0ea6Srdzhabarov auto it = symbolInfoMap.find(name.str()); 539ac68637bSLei Zhang if (it == symbolInfoMap.end()) { 540ac68637bSLei Zhang auto error = formatv("referencing unbound symbol '{0}'", symbol); 541ac68637bSLei Zhang PrintFatalError(loc, error); 542ac68637bSLei Zhang } 543ac68637bSLei Zhang 544008c0ea6Srdzhabarov return it->second.getValueAndRangeUse(name, index, fmt, separator); 54531cfee60SLei Zhang } 54631cfee60SLei Zhang 54712d16de5SRahul Joshi std::string SymbolInfoMap::getAllRangeUse(StringRef symbol, const char *fmt, 54831cfee60SLei Zhang const char *separator) const { 54931cfee60SLei Zhang int index = -1; 55031cfee60SLei Zhang StringRef name = getValuePackName(symbol, &index); 55131cfee60SLei Zhang 552008c0ea6Srdzhabarov auto it = symbolInfoMap.find(name.str()); 55331cfee60SLei Zhang if (it == symbolInfoMap.end()) { 55431cfee60SLei Zhang auto error = formatv("referencing unbound symbol '{0}'", symbol); 55531cfee60SLei Zhang PrintFatalError(loc, error); 55631cfee60SLei Zhang } 55731cfee60SLei Zhang 558008c0ea6Srdzhabarov return it->second.getAllRangeUse(name, index, fmt, separator); 559008c0ea6Srdzhabarov } 560008c0ea6Srdzhabarov 561008c0ea6Srdzhabarov void SymbolInfoMap::assignUniqueAlternativeNames() { 562008c0ea6Srdzhabarov llvm::StringSet<> usedNames; 563008c0ea6Srdzhabarov 564008c0ea6Srdzhabarov for (auto symbolInfoIt = symbolInfoMap.begin(); 565008c0ea6Srdzhabarov symbolInfoIt != symbolInfoMap.end();) { 566008c0ea6Srdzhabarov auto range = symbolInfoMap.equal_range(symbolInfoIt->first); 567008c0ea6Srdzhabarov auto startRange = range.first; 568008c0ea6Srdzhabarov auto endRange = range.second; 569008c0ea6Srdzhabarov 570008c0ea6Srdzhabarov auto operandName = symbolInfoIt->first; 571008c0ea6Srdzhabarov int startSearchIndex = 0; 572008c0ea6Srdzhabarov for (++startRange; startRange != endRange; ++startRange) { 573008c0ea6Srdzhabarov // Current operand name is not unique, find a unique one 574008c0ea6Srdzhabarov // and set the alternative name. 575008c0ea6Srdzhabarov for (int i = startSearchIndex;; ++i) { 576008c0ea6Srdzhabarov std::string alternativeName = operandName + std::to_string(i); 577008c0ea6Srdzhabarov if (!usedNames.contains(alternativeName) && 578008c0ea6Srdzhabarov symbolInfoMap.count(alternativeName) == 0) { 579008c0ea6Srdzhabarov usedNames.insert(alternativeName); 580008c0ea6Srdzhabarov startRange->second.alternativeName = alternativeName; 581008c0ea6Srdzhabarov startSearchIndex = i + 1; 582008c0ea6Srdzhabarov 583008c0ea6Srdzhabarov break; 584008c0ea6Srdzhabarov } 585008c0ea6Srdzhabarov } 586008c0ea6Srdzhabarov } 587008c0ea6Srdzhabarov 588008c0ea6Srdzhabarov symbolInfoIt = endRange; 589008c0ea6Srdzhabarov } 590ac68637bSLei Zhang } 591ac68637bSLei Zhang 592ac68637bSLei Zhang //===----------------------------------------------------------------------===// 593ac68637bSLei Zhang // Pattern 594ac68637bSLei Zhang //==----------------------------------------------------------------------===// 595ac68637bSLei Zhang 59612d16de5SRahul Joshi Pattern::Pattern(const llvm::Record *def, RecordOperatorMap *mapper) 597ac68637bSLei Zhang : def(*def), recordOpMap(mapper) {} 598eb753f4aSLei Zhang 59912d16de5SRahul Joshi DagNode Pattern::getSourcePattern() const { 60012d16de5SRahul Joshi return DagNode(def.getValueAsDag("sourcePattern")); 601eb753f4aSLei Zhang } 602eb753f4aSLei Zhang 60312d16de5SRahul Joshi int Pattern::getNumResultPatterns() const { 6048f5fa566SLei Zhang auto *results = def.getValueAsListInit("resultPatterns"); 605eb753f4aSLei Zhang return results->size(); 606eb753f4aSLei Zhang } 607eb753f4aSLei Zhang 60812d16de5SRahul Joshi DagNode Pattern::getResultPattern(unsigned index) const { 6098f5fa566SLei Zhang auto *results = def.getValueAsListInit("resultPatterns"); 61012d16de5SRahul Joshi return DagNode(cast<llvm::DagInit>(results->getElement(index))); 611eb753f4aSLei Zhang } 612eb753f4aSLei Zhang 61312d16de5SRahul Joshi void Pattern::collectSourcePatternBoundSymbols(SymbolInfoMap &infoMap) { 6141358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "start collecting source pattern bound symbols\n"); 615ac68637bSLei Zhang collectBoundSymbols(getSourcePattern(), infoMap, /*isSrcPattern=*/true); 6161358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "done collecting source pattern bound symbols\n"); 617008c0ea6Srdzhabarov 618008c0ea6Srdzhabarov LLVM_DEBUG(llvm::dbgs() << "start assigning alternative names for symbols\n"); 619008c0ea6Srdzhabarov infoMap.assignUniqueAlternativeNames(); 620008c0ea6Srdzhabarov LLVM_DEBUG(llvm::dbgs() << "done assigning alternative names for symbols\n"); 621eb753f4aSLei Zhang } 622eb753f4aSLei Zhang 62312d16de5SRahul Joshi void Pattern::collectResultPatternBoundSymbols(SymbolInfoMap &infoMap) { 6241358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "start collecting result pattern bound symbols\n"); 625ac68637bSLei Zhang for (int i = 0, e = getNumResultPatterns(); i < e; ++i) { 626ac68637bSLei Zhang auto pattern = getResultPattern(i); 627ac68637bSLei Zhang collectBoundSymbols(pattern, infoMap, /*isSrcPattern=*/false); 628eb753f4aSLei Zhang } 6291358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "done collecting result pattern bound symbols\n"); 630388fb375SJacques Pienaar } 631388fb375SJacques Pienaar 63212d16de5SRahul Joshi const Operator &Pattern::getSourceRootOp() { 633eb753f4aSLei Zhang return getSourcePattern().getDialectOp(recordOpMap); 634eb753f4aSLei Zhang } 635eb753f4aSLei Zhang 63612d16de5SRahul Joshi Operator &Pattern::getDialectOp(DagNode node) { 637eb753f4aSLei Zhang return node.getDialectOp(recordOpMap); 638eb753f4aSLei Zhang } 639388fb375SJacques Pienaar 64012d16de5SRahul Joshi std::vector<AppliedConstraint> Pattern::getConstraints() const { 641388fb375SJacques Pienaar auto *listInit = def.getValueAsListInit("constraints"); 64212d16de5SRahul Joshi std::vector<AppliedConstraint> ret; 643388fb375SJacques Pienaar ret.reserve(listInit->size()); 6448f5fa566SLei Zhang 645388fb375SJacques Pienaar for (auto it : *listInit) { 6468f5fa566SLei Zhang auto *dagInit = dyn_cast<llvm::DagInit>(it); 6478f5fa566SLei Zhang if (!dagInit) 6482bf423b0SRob Suderman PrintFatalError(&def, "all elements in Pattern multi-entity " 6498f5fa566SLei Zhang "constraints should be DAG nodes"); 6508f5fa566SLei Zhang 6518f5fa566SLei Zhang std::vector<std::string> entities; 6528f5fa566SLei Zhang entities.reserve(dagInit->arg_size()); 653cb40e36dSLei Zhang for (auto *argName : dagInit->getArgNames()) { 654cb40e36dSLei Zhang if (!argName) { 655cb40e36dSLei Zhang PrintFatalError( 6562bf423b0SRob Suderman &def, 657cb40e36dSLei Zhang "operands to additional constraints can only be symbol references"); 658cb40e36dSLei Zhang } 659adcd0268SBenjamin Kramer entities.push_back(std::string(argName->getValue())); 660cb40e36dSLei Zhang } 6618f5fa566SLei Zhang 6628f5fa566SLei Zhang ret.emplace_back(cast<llvm::DefInit>(dagInit->getOperator())->getDef(), 663c72d849eSLei Zhang dagInit->getNameStr(), std::move(entities)); 664388fb375SJacques Pienaar } 665388fb375SJacques Pienaar return ret; 666388fb375SJacques Pienaar } 66753035874SFeng Liu 66812d16de5SRahul Joshi int Pattern::getBenefit() const { 669a0606ca7SFeng Liu // The initial benefit value is a heuristic with number of ops in the source 67053035874SFeng Liu // pattern. 671a0606ca7SFeng Liu int initBenefit = getSourcePattern().getNumOps(); 67253035874SFeng Liu llvm::DagInit *delta = def.getValueAsDag("benefitDelta"); 673a0606ca7SFeng Liu if (delta->getNumArgs() != 1 || !isa<llvm::IntInit>(delta->getArg(0))) { 6742bf423b0SRob Suderman PrintFatalError(&def, 675a0606ca7SFeng Liu "The 'addBenefit' takes and only takes one integer value"); 676a0606ca7SFeng Liu } 677a0606ca7SFeng Liu return initBenefit + dyn_cast<llvm::IntInit>(delta->getArg(0))->getValue(); 67853035874SFeng Liu } 67904b6d2f3SLei Zhang 68012d16de5SRahul Joshi std::vector<Pattern::IdentifierLine> Pattern::getLocation() const { 6814165885aSJacques Pienaar std::vector<std::pair<StringRef, unsigned>> result; 6824165885aSJacques Pienaar result.reserve(def.getLoc().size()); 6834165885aSJacques Pienaar for (auto loc : def.getLoc()) { 6844165885aSJacques Pienaar unsigned buf = llvm::SrcMgr.FindBufferContainingLoc(loc); 6854165885aSJacques Pienaar assert(buf && "invalid source location"); 6864165885aSJacques Pienaar result.emplace_back( 6874165885aSJacques Pienaar llvm::SrcMgr.getBufferInfo(buf).Buffer->getBufferIdentifier(), 6884165885aSJacques Pienaar llvm::SrcMgr.getLineAndColumn(loc, buf).first); 6894165885aSJacques Pienaar } 6904165885aSJacques Pienaar return result; 6914165885aSJacques Pienaar } 6924165885aSJacques Pienaar 6932bf423b0SRob Suderman void Pattern::verifyBind(bool result, StringRef symbolName) { 6942bf423b0SRob Suderman if (!result) { 6952bf423b0SRob Suderman auto err = formatv("symbol '{0}' bound more than once", symbolName); 6962bf423b0SRob Suderman PrintFatalError(&def, err); 6972bf423b0SRob Suderman } 6982bf423b0SRob Suderman } 6992bf423b0SRob Suderman 70012d16de5SRahul Joshi void Pattern::collectBoundSymbols(DagNode tree, SymbolInfoMap &infoMap, 701e032d0dcSLei Zhang bool isSrcPattern) { 702e032d0dcSLei Zhang auto treeName = tree.getSymbol(); 7032bf423b0SRob Suderman auto numTreeArgs = tree.getNumArgs(); 7042bf423b0SRob Suderman 7052bf423b0SRob Suderman if (tree.isNativeCodeCall()) { 706e032d0dcSLei Zhang if (!treeName.empty()) { 70734b5482bSChia-hung Duan if (!isSrcPattern) { 70834b5482bSChia-hung Duan LLVM_DEBUG(llvm::dbgs() << "found symbol bound to NativeCodeCall: " 70934b5482bSChia-hung Duan << treeName << '\n'); 710d7314b3cSChia-hung Duan verifyBind( 711d7314b3cSChia-hung Duan infoMap.bindValues(treeName, tree.getNumReturnsOfNativeCode()), 712d7314b3cSChia-hung Duan treeName); 71334b5482bSChia-hung Duan } else { 71434b5482bSChia-hung Duan PrintFatalError(&def, 71534b5482bSChia-hung Duan formatv("binding symbol '{0}' to NativecodeCall in " 71634b5482bSChia-hung Duan "MatchPattern is not supported", 717e032d0dcSLei Zhang treeName)); 718e032d0dcSLei Zhang } 71934b5482bSChia-hung Duan } 7202bf423b0SRob Suderman 7212bf423b0SRob Suderman for (int i = 0; i != numTreeArgs; ++i) { 7222bf423b0SRob Suderman if (auto treeArg = tree.getArgAsNestedDag(i)) { 7232bf423b0SRob Suderman // This DAG node argument is a DAG node itself. Go inside recursively. 7242bf423b0SRob Suderman collectBoundSymbols(treeArg, infoMap, isSrcPattern); 7252bf423b0SRob Suderman continue; 7262bf423b0SRob Suderman } 7272bf423b0SRob Suderman 7282bf423b0SRob Suderman if (!isSrcPattern) 7292bf423b0SRob Suderman continue; 7302bf423b0SRob Suderman 7312bf423b0SRob Suderman // We can only bind symbols to arguments in source pattern. Those 7322bf423b0SRob Suderman // symbols are referenced in result patterns. 7332bf423b0SRob Suderman auto treeArgName = tree.getArgName(i); 7342bf423b0SRob Suderman 7352bf423b0SRob Suderman // `$_` is a special symbol meaning ignore the current argument. 7362bf423b0SRob Suderman if (!treeArgName.empty() && treeArgName != "_") { 7372bf423b0SRob Suderman DagLeaf leaf = tree.getArgAsLeaf(i); 73834b5482bSChia-hung Duan 73934b5482bSChia-hung Duan // In (NativeCodeCall<"Foo($_self, $0, $1, $2)"> I8Attr:$a, I8:$b, $c), 74034b5482bSChia-hung Duan if (leaf.isUnspecified()) { 74134b5482bSChia-hung Duan // This is case of $c, a Value without any constraints. 74234b5482bSChia-hung Duan verifyBind(infoMap.bindValue(treeArgName), treeArgName); 74334b5482bSChia-hung Duan } else { 7442bf423b0SRob Suderman auto constraint = leaf.getAsConstraint(); 7452bf423b0SRob Suderman bool isAttr = leaf.isAttrMatcher() || leaf.isEnumAttrCase() || 7462bf423b0SRob Suderman leaf.isConstantAttr() || 7472bf423b0SRob Suderman constraint.getKind() == Constraint::Kind::CK_Attr; 7482bf423b0SRob Suderman 7492bf423b0SRob Suderman if (isAttr) { 75034b5482bSChia-hung Duan // This is case of $a, a binding to a certain attribute. 7512bf423b0SRob Suderman verifyBind(infoMap.bindAttr(treeArgName), treeArgName); 7522bf423b0SRob Suderman continue; 7532bf423b0SRob Suderman } 7542bf423b0SRob Suderman 75534b5482bSChia-hung Duan // This is case of $b, a binding to a certain type. 7562bf423b0SRob Suderman verifyBind(infoMap.bindValue(treeArgName), treeArgName); 7572bf423b0SRob Suderman } 7582bf423b0SRob Suderman } 75934b5482bSChia-hung Duan } 7602bf423b0SRob Suderman 761e032d0dcSLei Zhang return; 762e032d0dcSLei Zhang } 763e032d0dcSLei Zhang 7642bf423b0SRob Suderman if (tree.isOperation()) { 76504b6d2f3SLei Zhang auto &op = getDialectOp(tree); 76604b6d2f3SLei Zhang auto numOpArgs = op.getNumArgs(); 76704b6d2f3SLei Zhang 768cb8c30d3SMogball // The pattern might have trailing directives. 769cb8c30d3SMogball int numDirectives = 0; 770cb8c30d3SMogball for (int i = numTreeArgs - 1; i >= 0; --i) { 771cb8c30d3SMogball if (auto dagArg = tree.getArgAsNestedDag(i)) { 772cb8c30d3SMogball if (dagArg.isLocationDirective() || dagArg.isReturnTypeDirective()) 773cb8c30d3SMogball ++numDirectives; 774cb8c30d3SMogball else 775cb8c30d3SMogball break; 776cb8c30d3SMogball } 7773f7439b2SJacques Pienaar } 7783f7439b2SJacques Pienaar 779cb8c30d3SMogball if (numOpArgs != numTreeArgs - numDirectives) { 780ac68637bSLei Zhang auto err = formatv("op '{0}' argument number mismatch: " 78104b6d2f3SLei Zhang "{1} in pattern vs. {2} in definition", 782ac68637bSLei Zhang op.getOperationName(), numTreeArgs, numOpArgs); 7832bf423b0SRob Suderman PrintFatalError(&def, err); 78404b6d2f3SLei Zhang } 78504b6d2f3SLei Zhang 78604b6d2f3SLei Zhang // The name attached to the DAG node's operator is for representing the 78704b6d2f3SLei Zhang // results generated from this op. It should be remembered as bound results. 788ac68637bSLei Zhang if (!treeName.empty()) { 7891358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() 7901358df19SLei Zhang << "found symbol bound to op result: " << treeName << '\n'); 7912bf423b0SRob Suderman verifyBind(infoMap.bindOpResult(treeName, op), treeName); 792ac68637bSLei Zhang } 79304b6d2f3SLei Zhang 7942fe8ae4fSJacques Pienaar for (int i = 0; i != numTreeArgs; ++i) { 79504b6d2f3SLei Zhang if (auto treeArg = tree.getArgAsNestedDag(i)) { 79604b6d2f3SLei Zhang // This DAG node argument is a DAG node itself. Go inside recursively. 797ac68637bSLei Zhang collectBoundSymbols(treeArg, infoMap, isSrcPattern); 7982bf423b0SRob Suderman continue; 7992bf423b0SRob Suderman } 8002bf423b0SRob Suderman 8012bf423b0SRob Suderman if (isSrcPattern) { 802e032d0dcSLei Zhang // We can only bind symbols to op arguments in source pattern. Those 803e032d0dcSLei Zhang // symbols are referenced in result patterns. 80404b6d2f3SLei Zhang auto treeArgName = tree.getArgName(i); 8054982eaf8SLei Zhang // `$_` is a special symbol meaning ignore the current argument. 8064982eaf8SLei Zhang if (!treeArgName.empty() && treeArgName != "_") { 8071358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "found symbol bound to op argument: " 8081358df19SLei Zhang << treeArgName << '\n'); 809b4001ae8SChia-hung Duan verifyBind(infoMap.bindOpArgument(tree, treeArgName, op, i), 810b4001ae8SChia-hung Duan treeArgName); 811ac68637bSLei Zhang } 812ac68637bSLei Zhang } 81304b6d2f3SLei Zhang } 8142bf423b0SRob Suderman return; 81504b6d2f3SLei Zhang } 8162bf423b0SRob Suderman 8172bf423b0SRob Suderman if (!treeName.empty()) { 8182bf423b0SRob Suderman PrintFatalError( 8192bf423b0SRob Suderman &def, formatv("binding symbol '{0}' to non-operation/native code call " 8202bf423b0SRob Suderman "unsupported right now", 8212bf423b0SRob Suderman treeName)); 8222bf423b0SRob Suderman } 8232bf423b0SRob Suderman return; 82404b6d2f3SLei Zhang } 825