1cde4d5a6SJacques Pienaar //===- Pattern.cpp - Pattern wrapper class --------------------------------===// 2eb753f4aSLei Zhang // 3eb753f4aSLei Zhang // Copyright 2019 The MLIR Authors. 4eb753f4aSLei Zhang // 5eb753f4aSLei Zhang // Licensed under the Apache License, Version 2.0 (the "License"); 6eb753f4aSLei Zhang // you may not use this file except in compliance with the License. 7eb753f4aSLei Zhang // You may obtain a copy of the License at 8eb753f4aSLei Zhang // 9eb753f4aSLei Zhang // http://www.apache.org/licenses/LICENSE-2.0 10eb753f4aSLei Zhang // 11eb753f4aSLei Zhang // Unless required by applicable law or agreed to in writing, software 12eb753f4aSLei Zhang // distributed under the License is distributed on an "AS IS" BASIS, 13eb753f4aSLei Zhang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14eb753f4aSLei Zhang // See the License for the specific language governing permissions and 15eb753f4aSLei Zhang // limitations under the License. 16eb753f4aSLei Zhang // ============================================================================= 17eb753f4aSLei Zhang // 18eb753f4aSLei Zhang // Pattern wrapper class to simplify using TableGen Record defining a MLIR 19eb753f4aSLei Zhang // Pattern. 20eb753f4aSLei Zhang // 21eb753f4aSLei Zhang //===----------------------------------------------------------------------===// 22eb753f4aSLei Zhang 23eb753f4aSLei Zhang #include "mlir/TableGen/Pattern.h" 24eb753f4aSLei Zhang #include "llvm/ADT/Twine.h" 25*1358df19SLei Zhang #include "llvm/Support/Debug.h" 2604b6d2f3SLei Zhang #include "llvm/Support/FormatVariadic.h" 278f5fa566SLei Zhang #include "llvm/TableGen/Error.h" 28eb753f4aSLei Zhang #include "llvm/TableGen/Record.h" 29eb753f4aSLei Zhang 30*1358df19SLei Zhang #define DEBUG_TYPE "mlir-tblgen-pattern" 31*1358df19SLei Zhang 32eb753f4aSLei Zhang using namespace mlir; 33eb753f4aSLei Zhang 340ea6154bSJacques Pienaar using llvm::formatv; 35eb753f4aSLei Zhang using mlir::tblgen::Operator; 36eb753f4aSLei Zhang 37ac68637bSLei Zhang //===----------------------------------------------------------------------===// 38ac68637bSLei Zhang // DagLeaf 39ac68637bSLei Zhang //===----------------------------------------------------------------------===// 40ac68637bSLei Zhang 41e0774c00SLei Zhang bool tblgen::DagLeaf::isUnspecified() const { 42b9e38a79SLei Zhang return dyn_cast_or_null<llvm::UnsetInit>(def); 43e0774c00SLei Zhang } 44e0774c00SLei Zhang 45e0774c00SLei Zhang bool tblgen::DagLeaf::isOperandMatcher() const { 46e0774c00SLei Zhang // Operand matchers specify a type constraint. 47b9e38a79SLei Zhang return isSubClassOf("TypeConstraint"); 48e0774c00SLei Zhang } 49e0774c00SLei Zhang 50e0774c00SLei Zhang bool tblgen::DagLeaf::isAttrMatcher() const { 51c52a8127SFeng Liu // Attribute matchers specify an attribute constraint. 52b9e38a79SLei Zhang return isSubClassOf("AttrConstraint"); 53e0774c00SLei Zhang } 54e0774c00SLei Zhang 55d0e2019dSLei Zhang bool tblgen::DagLeaf::isNativeCodeCall() const { 56d0e2019dSLei Zhang return isSubClassOf("NativeCodeCall"); 57e0774c00SLei Zhang } 58e0774c00SLei Zhang 59e0774c00SLei Zhang bool tblgen::DagLeaf::isConstantAttr() const { 60b9e38a79SLei Zhang return isSubClassOf("ConstantAttr"); 61b9e38a79SLei Zhang } 62b9e38a79SLei Zhang 63b9e38a79SLei Zhang bool tblgen::DagLeaf::isEnumAttrCase() const { 649dd182e0SLei Zhang return isSubClassOf("EnumAttrCaseInfo"); 65e0774c00SLei Zhang } 66e0774c00SLei Zhang 678f5fa566SLei Zhang tblgen::Constraint tblgen::DagLeaf::getAsConstraint() const { 688f5fa566SLei Zhang assert((isOperandMatcher() || isAttrMatcher()) && 698f5fa566SLei Zhang "the DAG leaf must be operand or attribute"); 708f5fa566SLei Zhang return Constraint(cast<llvm::DefInit>(def)->getDef()); 71e0774c00SLei Zhang } 72e0774c00SLei Zhang 73e0774c00SLei Zhang tblgen::ConstantAttr tblgen::DagLeaf::getAsConstantAttr() const { 74e0774c00SLei Zhang assert(isConstantAttr() && "the DAG leaf must be constant attribute"); 75e0774c00SLei Zhang return ConstantAttr(cast<llvm::DefInit>(def)); 76e0774c00SLei Zhang } 77e0774c00SLei Zhang 78b9e38a79SLei Zhang tblgen::EnumAttrCase tblgen::DagLeaf::getAsEnumAttrCase() const { 79b9e38a79SLei Zhang assert(isEnumAttrCase() && "the DAG leaf must be an enum attribute case"); 80b9e38a79SLei Zhang return EnumAttrCase(cast<llvm::DefInit>(def)); 81b9e38a79SLei Zhang } 82b9e38a79SLei Zhang 83e0774c00SLei Zhang std::string tblgen::DagLeaf::getConditionTemplate() const { 848f5fa566SLei Zhang return getAsConstraint().getConditionTemplate(); 85e0774c00SLei Zhang } 86e0774c00SLei Zhang 87d0e2019dSLei Zhang llvm::StringRef tblgen::DagLeaf::getNativeCodeTemplate() const { 88d0e2019dSLei Zhang assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall"); 89d0e2019dSLei Zhang return cast<llvm::DefInit>(def)->getDef()->getValueAsString("expression"); 90eb753f4aSLei Zhang } 91eb753f4aSLei Zhang 92b9e38a79SLei Zhang bool tblgen::DagLeaf::isSubClassOf(StringRef superclass) const { 93b9e38a79SLei Zhang if (auto *defInit = dyn_cast_or_null<llvm::DefInit>(def)) 94b9e38a79SLei Zhang return defInit->getDef()->isSubClassOf(superclass); 95b9e38a79SLei Zhang return false; 96b9e38a79SLei Zhang } 97b9e38a79SLei Zhang 98*1358df19SLei Zhang void tblgen::DagLeaf::print(raw_ostream &os) const { 99*1358df19SLei Zhang if (def) 100*1358df19SLei Zhang def->print(os); 101*1358df19SLei Zhang } 102*1358df19SLei Zhang 103ac68637bSLei Zhang //===----------------------------------------------------------------------===// 104ac68637bSLei Zhang // DagNode 105ac68637bSLei Zhang //===----------------------------------------------------------------------===// 106ac68637bSLei Zhang 107d0e2019dSLei Zhang bool tblgen::DagNode::isNativeCodeCall() const { 108d0e2019dSLei Zhang if (auto *defInit = dyn_cast_or_null<llvm::DefInit>(node->getOperator())) 109d0e2019dSLei Zhang return defInit->getDef()->isSubClassOf("NativeCodeCall"); 110c52a8127SFeng Liu return false; 111c52a8127SFeng Liu } 112c52a8127SFeng Liu 113647f8cabSRiver Riddle bool tblgen::DagNode::isOperation() const { 114c72d849eSLei Zhang return !(isNativeCodeCall() || isReplaceWithValue()); 115647f8cabSRiver Riddle } 116647f8cabSRiver Riddle 117d0e2019dSLei Zhang llvm::StringRef tblgen::DagNode::getNativeCodeTemplate() const { 118d0e2019dSLei Zhang assert(isNativeCodeCall() && "the DAG leaf must be NativeCodeCall"); 119c52a8127SFeng Liu return cast<llvm::DefInit>(node->getOperator()) 120c52a8127SFeng Liu ->getDef() 121d0e2019dSLei Zhang ->getValueAsString("expression"); 122c52a8127SFeng Liu } 123c52a8127SFeng Liu 124e032d0dcSLei Zhang llvm::StringRef tblgen::DagNode::getSymbol() const { 125388fb375SJacques Pienaar return node->getNameStr(); 126388fb375SJacques Pienaar } 127388fb375SJacques Pienaar 128eb753f4aSLei Zhang Operator &tblgen::DagNode::getDialectOp(RecordOperatorMap *mapper) const { 129eb753f4aSLei Zhang llvm::Record *opDef = cast<llvm::DefInit>(node->getOperator())->getDef(); 1302dc6d205SLei Zhang auto it = mapper->find(opDef); 1312dc6d205SLei Zhang if (it != mapper->end()) 1322dc6d205SLei Zhang return *it->second; 13379f53b0cSJacques Pienaar return *mapper->try_emplace(opDef, std::make_unique<Operator>(opDef)) 1342dc6d205SLei Zhang .first->second; 135eb753f4aSLei Zhang } 136eb753f4aSLei Zhang 1372fe8ae4fSJacques Pienaar int tblgen::DagNode::getNumOps() const { 1382fe8ae4fSJacques Pienaar int count = isReplaceWithValue() ? 0 : 1; 1392fe8ae4fSJacques Pienaar for (int i = 0, e = getNumArgs(); i != e; ++i) { 140eb753f4aSLei Zhang if (auto child = getArgAsNestedDag(i)) 141eb753f4aSLei Zhang count += child.getNumOps(); 142eb753f4aSLei Zhang } 143eb753f4aSLei Zhang return count; 144eb753f4aSLei Zhang } 145eb753f4aSLei Zhang 1462fe8ae4fSJacques Pienaar int tblgen::DagNode::getNumArgs() const { return node->getNumArgs(); } 147eb753f4aSLei Zhang 148eb753f4aSLei Zhang bool tblgen::DagNode::isNestedDagArg(unsigned index) const { 149eb753f4aSLei Zhang return isa<llvm::DagInit>(node->getArg(index)); 150eb753f4aSLei Zhang } 151eb753f4aSLei Zhang 152eb753f4aSLei Zhang tblgen::DagNode tblgen::DagNode::getArgAsNestedDag(unsigned index) const { 153eb753f4aSLei Zhang return DagNode(dyn_cast_or_null<llvm::DagInit>(node->getArg(index))); 154eb753f4aSLei Zhang } 155eb753f4aSLei Zhang 156e0774c00SLei Zhang tblgen::DagLeaf tblgen::DagNode::getArgAsLeaf(unsigned index) const { 157e0774c00SLei Zhang assert(!isNestedDagArg(index)); 158e0774c00SLei Zhang return DagLeaf(node->getArg(index)); 159eb753f4aSLei Zhang } 160eb753f4aSLei Zhang 161eb753f4aSLei Zhang StringRef tblgen::DagNode::getArgName(unsigned index) const { 162eb753f4aSLei Zhang return node->getArgNameStr(index); 163eb753f4aSLei Zhang } 164eb753f4aSLei Zhang 165eb753f4aSLei Zhang bool tblgen::DagNode::isReplaceWithValue() const { 166eb753f4aSLei Zhang auto *dagOpDef = cast<llvm::DefInit>(node->getOperator())->getDef(); 167eb753f4aSLei Zhang return dagOpDef->getName() == "replaceWithValue"; 168eb753f4aSLei Zhang } 169eb753f4aSLei Zhang 170*1358df19SLei Zhang void tblgen::DagNode::print(raw_ostream &os) const { 171*1358df19SLei Zhang if (node) 172*1358df19SLei Zhang node->print(os); 173*1358df19SLei Zhang } 174*1358df19SLei Zhang 175ac68637bSLei Zhang //===----------------------------------------------------------------------===// 176ac68637bSLei Zhang // SymbolInfoMap 177ac68637bSLei Zhang //===----------------------------------------------------------------------===// 178ac68637bSLei Zhang 179ac68637bSLei Zhang StringRef tblgen::SymbolInfoMap::getValuePackName(StringRef symbol, 180ac68637bSLei Zhang int *index) { 181ac68637bSLei Zhang StringRef name, indexStr; 182ac68637bSLei Zhang int idx = -1; 183ac68637bSLei Zhang std::tie(name, indexStr) = symbol.rsplit("__"); 184ac68637bSLei Zhang 185ac68637bSLei Zhang if (indexStr.consumeInteger(10, idx)) { 186ac68637bSLei Zhang // The second part is not an index; we return the whole symbol as-is. 187ac68637bSLei Zhang return symbol; 188eb753f4aSLei Zhang } 189ac68637bSLei Zhang if (index) { 190ac68637bSLei Zhang *index = idx; 191ac68637bSLei Zhang } 192ac68637bSLei Zhang return name; 193ac68637bSLei Zhang } 194ac68637bSLei Zhang 195ac68637bSLei Zhang tblgen::SymbolInfoMap::SymbolInfo::SymbolInfo(const Operator *op, 196ac68637bSLei Zhang SymbolInfo::Kind kind, 197ac68637bSLei Zhang Optional<int> index) 198ac68637bSLei Zhang : op(op), kind(kind), argIndex(index) {} 199ac68637bSLei Zhang 200ac68637bSLei Zhang int tblgen::SymbolInfoMap::SymbolInfo::getStaticValueCount() const { 201ac68637bSLei Zhang switch (kind) { 202ac68637bSLei Zhang case Kind::Attr: 203ac68637bSLei Zhang case Kind::Operand: 204ac68637bSLei Zhang case Kind::Value: 205ac68637bSLei Zhang return 1; 206ac68637bSLei Zhang case Kind::Result: 207ac68637bSLei Zhang return op->getNumResults(); 208ac68637bSLei Zhang } 20912ff145eSjpienaar llvm_unreachable("unknown kind"); 210ac68637bSLei Zhang } 211ac68637bSLei Zhang 212ac68637bSLei Zhang std::string 213ac68637bSLei Zhang tblgen::SymbolInfoMap::SymbolInfo::getVarDecl(StringRef name) const { 214ac68637bSLei Zhang switch (kind) { 215ac68637bSLei Zhang case Kind::Attr: { 216ac68637bSLei Zhang auto type = 217ac68637bSLei Zhang op->getArg(*argIndex).get<NamedAttribute *>()->attr.getStorageType(); 218ac68637bSLei Zhang return formatv("{0} {1};\n", type, name); 219ac68637bSLei Zhang } 22031cfee60SLei Zhang case Kind::Operand: { 22131cfee60SLei Zhang // Use operand range for captured operands (to support potential variadic 22231cfee60SLei Zhang // operands). 22331cfee60SLei Zhang return formatv("Operation::operand_range {0}(op0->getOperands());\n", name); 22431cfee60SLei Zhang } 225ac68637bSLei Zhang case Kind::Value: { 22631cfee60SLei Zhang return formatv("ArrayRef<Value *> {0};\n", name); 227ac68637bSLei Zhang } 228ac68637bSLei Zhang case Kind::Result: { 22931cfee60SLei Zhang // Use the op itself for captured results. 230ac68637bSLei Zhang return formatv("{0} {1};\n", op->getQualCppClassName(), name); 231ac68637bSLei Zhang } 232ac68637bSLei Zhang } 23312ff145eSjpienaar llvm_unreachable("unknown kind"); 234ac68637bSLei Zhang } 235ac68637bSLei Zhang 23631cfee60SLei Zhang std::string tblgen::SymbolInfoMap::SymbolInfo::getValueAndRangeUse( 23731cfee60SLei Zhang StringRef name, int index, const char *fmt, const char *separator) const { 238*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "getValueAndRangeUse for '" << name << "': "); 23931cfee60SLei Zhang switch (kind) { 24031cfee60SLei Zhang case Kind::Attr: { 24131cfee60SLei Zhang assert(index < 0); 242*1358df19SLei Zhang auto repl = formatv(fmt, name); 243*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (Attr)\n"); 244*1358df19SLei Zhang return repl; 24531cfee60SLei Zhang } 24631cfee60SLei Zhang case Kind::Operand: { 24731cfee60SLei Zhang assert(index < 0); 24831cfee60SLei Zhang auto *operand = op->getArg(*argIndex).get<NamedTypeConstraint *>(); 24931cfee60SLei Zhang // If this operand is variadic, then return a range. Otherwise, return the 25031cfee60SLei Zhang // value itself. 25131cfee60SLei Zhang if (operand->isVariadic()) { 252*1358df19SLei Zhang auto repl = formatv(fmt, name); 253*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (VariadicOperand)\n"); 254*1358df19SLei Zhang return repl; 25531cfee60SLei Zhang } 256*1358df19SLei Zhang auto repl = formatv(fmt, formatv("(*{0}.begin())", name)); 257*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (SingleOperand)\n"); 258*1358df19SLei Zhang return repl; 25931cfee60SLei Zhang } 26031cfee60SLei Zhang case Kind::Result: { 26131cfee60SLei Zhang // If `index` is greater than zero, then we are referencing a specific 26231cfee60SLei Zhang // result of a multi-result op. The result can still be variadic. 26331cfee60SLei Zhang if (index >= 0) { 26431cfee60SLei Zhang std::string v = formatv("{0}.getODSResults({1})", name, index); 26531cfee60SLei Zhang if (!op->getResult(index).isVariadic()) 26631cfee60SLei Zhang v = formatv("(*{0}.begin())", v); 267*1358df19SLei Zhang auto repl = formatv(fmt, v); 268*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (SingleResult)\n"); 269*1358df19SLei Zhang return repl; 27031cfee60SLei Zhang } 27131cfee60SLei Zhang 27231cfee60SLei Zhang // We are referencing all results of the multi-result op. A specific result 27331cfee60SLei Zhang // can either be a value or a range. Then join them with `separator`. 27431cfee60SLei Zhang SmallVector<std::string, 4> values; 27531cfee60SLei Zhang values.reserve(op->getNumResults()); 27631cfee60SLei Zhang 27731cfee60SLei Zhang for (int i = 0, e = op->getNumResults(); i < e; ++i) { 27831cfee60SLei Zhang std::string v = formatv("{0}.getODSResults({1})", name, i); 27931cfee60SLei Zhang if (!op->getResult(i).isVariadic()) { 28031cfee60SLei Zhang v = formatv("(*{0}.begin())", v); 28131cfee60SLei Zhang } 28231cfee60SLei Zhang values.push_back(formatv(fmt, v)); 28331cfee60SLei Zhang } 284*1358df19SLei Zhang auto repl = llvm::join(values, separator); 285*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (VariadicResult)\n"); 286*1358df19SLei Zhang return repl; 28731cfee60SLei Zhang } 28831cfee60SLei Zhang case Kind::Value: { 28931cfee60SLei Zhang assert(index < 0); 29031cfee60SLei Zhang assert(op == nullptr); 291*1358df19SLei Zhang auto repl = formatv(fmt, name); 292*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (Value)\n"); 293*1358df19SLei Zhang return repl; 29431cfee60SLei Zhang } 29531cfee60SLei Zhang } 29694298ceaSLei Zhang llvm_unreachable("unknown kind"); 29731cfee60SLei Zhang } 29831cfee60SLei Zhang 29931cfee60SLei Zhang std::string tblgen::SymbolInfoMap::SymbolInfo::getAllRangeUse( 30031cfee60SLei Zhang StringRef name, int index, const char *fmt, const char *separator) const { 301*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "getAllRangeUse for '" << name << "': "); 302ac68637bSLei Zhang switch (kind) { 303ac68637bSLei Zhang case Kind::Attr: 304ac68637bSLei Zhang case Kind::Operand: { 305ac68637bSLei Zhang assert(index < 0 && "only allowed for symbol bound to result"); 306*1358df19SLei Zhang auto repl = formatv(fmt, name); 307*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (Operand/Attr)\n"); 308*1358df19SLei Zhang return repl; 309ac68637bSLei Zhang } 310ac68637bSLei Zhang case Kind::Result: { 311ac68637bSLei Zhang if (index >= 0) { 312*1358df19SLei Zhang auto repl = formatv(fmt, formatv("{0}.getODSResults({1})", name, index)); 313*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (SingleResult)\n"); 314*1358df19SLei Zhang return repl; 315ac68637bSLei Zhang } 316ac68637bSLei Zhang 31731cfee60SLei Zhang // We are referencing all results of the multi-result op. Each result should 31831cfee60SLei Zhang // have a value range, and then join them with `separator`. 319ac68637bSLei Zhang SmallVector<std::string, 4> values; 32031cfee60SLei Zhang values.reserve(op->getNumResults()); 32131cfee60SLei Zhang 322ac68637bSLei Zhang for (int i = 0, e = op->getNumResults(); i < e; ++i) { 32331cfee60SLei Zhang values.push_back( 32431cfee60SLei Zhang formatv(fmt, formatv("{0}.getODSResults({1})", name, i))); 325ac68637bSLei Zhang } 326*1358df19SLei Zhang auto repl = llvm::join(values, separator); 327*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (VariadicResult)\n"); 328*1358df19SLei Zhang return repl; 329ac68637bSLei Zhang } 330ac68637bSLei Zhang case Kind::Value: { 331ac68637bSLei Zhang assert(index < 0 && "only allowed for symbol bound to result"); 332ac68637bSLei Zhang assert(op == nullptr); 333*1358df19SLei Zhang auto repl = formatv(fmt, formatv("{{{0}}", name)); 334*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << repl << " (Value)\n"); 335*1358df19SLei Zhang return repl; 336ac68637bSLei Zhang } 337ac68637bSLei Zhang } 33812ff145eSjpienaar llvm_unreachable("unknown kind"); 339ac68637bSLei Zhang } 340ac68637bSLei Zhang 341ac68637bSLei Zhang bool tblgen::SymbolInfoMap::bindOpArgument(StringRef symbol, const Operator &op, 342ac68637bSLei Zhang int argIndex) { 343ac68637bSLei Zhang StringRef name = getValuePackName(symbol); 344ac68637bSLei Zhang if (name != symbol) { 345ac68637bSLei Zhang auto error = formatv( 346ac68637bSLei Zhang "symbol '{0}' with trailing index cannot bind to op argument", symbol); 347ac68637bSLei Zhang PrintFatalError(loc, error); 348ac68637bSLei Zhang } 349ac68637bSLei Zhang 350ac68637bSLei Zhang auto symInfo = op.getArg(argIndex).is<NamedAttribute *>() 351ac68637bSLei Zhang ? SymbolInfo::getAttr(&op, argIndex) 352ac68637bSLei Zhang : SymbolInfo::getOperand(&op, argIndex); 353ac68637bSLei Zhang 354ac68637bSLei Zhang return symbolInfoMap.insert({symbol, symInfo}).second; 355ac68637bSLei Zhang } 356ac68637bSLei Zhang 357ac68637bSLei Zhang bool tblgen::SymbolInfoMap::bindOpResult(StringRef symbol, const Operator &op) { 358ac68637bSLei Zhang StringRef name = getValuePackName(symbol); 359ac68637bSLei Zhang return symbolInfoMap.insert({name, SymbolInfo::getResult(&op)}).second; 360ac68637bSLei Zhang } 361ac68637bSLei Zhang 362ac68637bSLei Zhang bool tblgen::SymbolInfoMap::bindValue(StringRef symbol) { 363ac68637bSLei Zhang return symbolInfoMap.insert({symbol, SymbolInfo::getValue()}).second; 364ac68637bSLei Zhang } 365ac68637bSLei Zhang 366ac68637bSLei Zhang bool tblgen::SymbolInfoMap::contains(StringRef symbol) const { 367ac68637bSLei Zhang return find(symbol) != symbolInfoMap.end(); 368ac68637bSLei Zhang } 369ac68637bSLei Zhang 370ac68637bSLei Zhang tblgen::SymbolInfoMap::const_iterator 371ac68637bSLei Zhang tblgen::SymbolInfoMap::find(StringRef key) const { 372ac68637bSLei Zhang StringRef name = getValuePackName(key); 373ac68637bSLei Zhang return symbolInfoMap.find(name); 374ac68637bSLei Zhang } 375ac68637bSLei Zhang 376ac68637bSLei Zhang int tblgen::SymbolInfoMap::getStaticValueCount(StringRef symbol) const { 377ac68637bSLei Zhang StringRef name = getValuePackName(symbol); 378ac68637bSLei Zhang if (name != symbol) { 379ac68637bSLei Zhang // If there is a trailing index inside symbol, it references just one 380ac68637bSLei Zhang // static value. 381ac68637bSLei Zhang return 1; 382ac68637bSLei Zhang } 383ac68637bSLei Zhang // Otherwise, find how many it represents by querying the symbol's info. 384ac68637bSLei Zhang return find(name)->getValue().getStaticValueCount(); 385ac68637bSLei Zhang } 386ac68637bSLei Zhang 38731cfee60SLei Zhang std::string 38831cfee60SLei Zhang tblgen::SymbolInfoMap::getValueAndRangeUse(StringRef symbol, const char *fmt, 38931cfee60SLei Zhang const char *separator) const { 390ac68637bSLei Zhang int index = -1; 391ac68637bSLei Zhang StringRef name = getValuePackName(symbol, &index); 392ac68637bSLei Zhang 393ac68637bSLei Zhang auto it = symbolInfoMap.find(name); 394ac68637bSLei Zhang if (it == symbolInfoMap.end()) { 395ac68637bSLei Zhang auto error = formatv("referencing unbound symbol '{0}'", symbol); 396ac68637bSLei Zhang PrintFatalError(loc, error); 397ac68637bSLei Zhang } 398ac68637bSLei Zhang 39931cfee60SLei Zhang return it->getValue().getValueAndRangeUse(name, index, fmt, separator); 40031cfee60SLei Zhang } 40131cfee60SLei Zhang 40231cfee60SLei Zhang std::string tblgen::SymbolInfoMap::getAllRangeUse(StringRef symbol, 40331cfee60SLei Zhang const char *fmt, 40431cfee60SLei Zhang const char *separator) const { 40531cfee60SLei Zhang int index = -1; 40631cfee60SLei Zhang StringRef name = getValuePackName(symbol, &index); 40731cfee60SLei Zhang 40831cfee60SLei Zhang auto it = symbolInfoMap.find(name); 40931cfee60SLei Zhang if (it == symbolInfoMap.end()) { 41031cfee60SLei Zhang auto error = formatv("referencing unbound symbol '{0}'", symbol); 41131cfee60SLei Zhang PrintFatalError(loc, error); 41231cfee60SLei Zhang } 41331cfee60SLei Zhang 41431cfee60SLei Zhang return it->getValue().getAllRangeUse(name, index, fmt, separator); 415ac68637bSLei Zhang } 416ac68637bSLei Zhang 417ac68637bSLei Zhang //===----------------------------------------------------------------------===// 418ac68637bSLei Zhang // Pattern 419ac68637bSLei Zhang //==----------------------------------------------------------------------===// 420ac68637bSLei Zhang 421ac68637bSLei Zhang tblgen::Pattern::Pattern(const llvm::Record *def, RecordOperatorMap *mapper) 422ac68637bSLei Zhang : def(*def), recordOpMap(mapper) {} 423eb753f4aSLei Zhang 424eb753f4aSLei Zhang tblgen::DagNode tblgen::Pattern::getSourcePattern() const { 4258f5fa566SLei Zhang return tblgen::DagNode(def.getValueAsDag("sourcePattern")); 426eb753f4aSLei Zhang } 427eb753f4aSLei Zhang 428e032d0dcSLei Zhang int tblgen::Pattern::getNumResultPatterns() const { 4298f5fa566SLei Zhang auto *results = def.getValueAsListInit("resultPatterns"); 430eb753f4aSLei Zhang return results->size(); 431eb753f4aSLei Zhang } 432eb753f4aSLei Zhang 433eb753f4aSLei Zhang tblgen::DagNode tblgen::Pattern::getResultPattern(unsigned index) const { 4348f5fa566SLei Zhang auto *results = def.getValueAsListInit("resultPatterns"); 435eb753f4aSLei Zhang return tblgen::DagNode(cast<llvm::DagInit>(results->getElement(index))); 436eb753f4aSLei Zhang } 437eb753f4aSLei Zhang 438ac68637bSLei Zhang void tblgen::Pattern::collectSourcePatternBoundSymbols( 439ac68637bSLei Zhang tblgen::SymbolInfoMap &infoMap) { 440*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "start collecting source pattern bound symbols\n"); 441ac68637bSLei Zhang collectBoundSymbols(getSourcePattern(), infoMap, /*isSrcPattern=*/true); 442*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "done collecting source pattern bound symbols\n"); 443eb753f4aSLei Zhang } 444eb753f4aSLei Zhang 445ac68637bSLei Zhang void tblgen::Pattern::collectResultPatternBoundSymbols( 446ac68637bSLei Zhang tblgen::SymbolInfoMap &infoMap) { 447*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "start collecting result pattern bound symbols\n"); 448ac68637bSLei Zhang for (int i = 0, e = getNumResultPatterns(); i < e; ++i) { 449ac68637bSLei Zhang auto pattern = getResultPattern(i); 450ac68637bSLei Zhang collectBoundSymbols(pattern, infoMap, /*isSrcPattern=*/false); 451eb753f4aSLei Zhang } 452*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "done collecting result pattern bound symbols\n"); 453388fb375SJacques Pienaar } 454388fb375SJacques Pienaar 455eb753f4aSLei Zhang const tblgen::Operator &tblgen::Pattern::getSourceRootOp() { 456eb753f4aSLei Zhang return getSourcePattern().getDialectOp(recordOpMap); 457eb753f4aSLei Zhang } 458eb753f4aSLei Zhang 459eb753f4aSLei Zhang tblgen::Operator &tblgen::Pattern::getDialectOp(DagNode node) { 460eb753f4aSLei Zhang return node.getDialectOp(recordOpMap); 461eb753f4aSLei Zhang } 462388fb375SJacques Pienaar 4638f5fa566SLei Zhang std::vector<tblgen::AppliedConstraint> tblgen::Pattern::getConstraints() const { 464388fb375SJacques Pienaar auto *listInit = def.getValueAsListInit("constraints"); 4658f5fa566SLei Zhang std::vector<tblgen::AppliedConstraint> ret; 466388fb375SJacques Pienaar ret.reserve(listInit->size()); 4678f5fa566SLei Zhang 468388fb375SJacques Pienaar for (auto it : *listInit) { 4698f5fa566SLei Zhang auto *dagInit = dyn_cast<llvm::DagInit>(it); 4708f5fa566SLei Zhang if (!dagInit) 4718f5fa566SLei Zhang PrintFatalError(def.getLoc(), "all elemements in Pattern multi-entity " 4728f5fa566SLei Zhang "constraints should be DAG nodes"); 4738f5fa566SLei Zhang 4748f5fa566SLei Zhang std::vector<std::string> entities; 4758f5fa566SLei Zhang entities.reserve(dagInit->arg_size()); 4768f5fa566SLei Zhang for (auto *argName : dagInit->getArgNames()) 4778f5fa566SLei Zhang entities.push_back(argName->getValue()); 4788f5fa566SLei Zhang 4798f5fa566SLei Zhang ret.emplace_back(cast<llvm::DefInit>(dagInit->getOperator())->getDef(), 480c72d849eSLei Zhang dagInit->getNameStr(), std::move(entities)); 481388fb375SJacques Pienaar } 482388fb375SJacques Pienaar return ret; 483388fb375SJacques Pienaar } 48453035874SFeng Liu 48553035874SFeng Liu int tblgen::Pattern::getBenefit() const { 486a0606ca7SFeng Liu // The initial benefit value is a heuristic with number of ops in the source 48753035874SFeng Liu // pattern. 488a0606ca7SFeng Liu int initBenefit = getSourcePattern().getNumOps(); 48953035874SFeng Liu llvm::DagInit *delta = def.getValueAsDag("benefitDelta"); 490a0606ca7SFeng Liu if (delta->getNumArgs() != 1 || !isa<llvm::IntInit>(delta->getArg(0))) { 491a0606ca7SFeng Liu PrintFatalError(def.getLoc(), 492a0606ca7SFeng Liu "The 'addBenefit' takes and only takes one integer value"); 493a0606ca7SFeng Liu } 494a0606ca7SFeng Liu return initBenefit + dyn_cast<llvm::IntInit>(delta->getArg(0))->getValue(); 49553035874SFeng Liu } 49604b6d2f3SLei Zhang 4974165885aSJacques Pienaar std::vector<tblgen::Pattern::IdentifierLine> 4984165885aSJacques Pienaar tblgen::Pattern::getLocation() const { 4994165885aSJacques Pienaar std::vector<std::pair<StringRef, unsigned>> result; 5004165885aSJacques Pienaar result.reserve(def.getLoc().size()); 5014165885aSJacques Pienaar for (auto loc : def.getLoc()) { 5024165885aSJacques Pienaar unsigned buf = llvm::SrcMgr.FindBufferContainingLoc(loc); 5034165885aSJacques Pienaar assert(buf && "invalid source location"); 5044165885aSJacques Pienaar result.emplace_back( 5054165885aSJacques Pienaar llvm::SrcMgr.getBufferInfo(buf).Buffer->getBufferIdentifier(), 5064165885aSJacques Pienaar llvm::SrcMgr.getLineAndColumn(loc, buf).first); 5074165885aSJacques Pienaar } 5084165885aSJacques Pienaar return result; 5094165885aSJacques Pienaar } 5104165885aSJacques Pienaar 511ac68637bSLei Zhang void tblgen::Pattern::collectBoundSymbols(DagNode tree, SymbolInfoMap &infoMap, 512e032d0dcSLei Zhang bool isSrcPattern) { 513e032d0dcSLei Zhang auto treeName = tree.getSymbol(); 514e032d0dcSLei Zhang if (!tree.isOperation()) { 515e032d0dcSLei Zhang if (!treeName.empty()) { 516e032d0dcSLei Zhang PrintFatalError( 517e032d0dcSLei Zhang def.getLoc(), 518e032d0dcSLei Zhang formatv("binding symbol '{0}' to non-operation unsupported right now", 519e032d0dcSLei Zhang treeName)); 520e032d0dcSLei Zhang } 521e032d0dcSLei Zhang return; 522e032d0dcSLei Zhang } 523e032d0dcSLei Zhang 52404b6d2f3SLei Zhang auto &op = getDialectOp(tree); 52504b6d2f3SLei Zhang auto numOpArgs = op.getNumArgs(); 52604b6d2f3SLei Zhang auto numTreeArgs = tree.getNumArgs(); 52704b6d2f3SLei Zhang 52804b6d2f3SLei Zhang if (numOpArgs != numTreeArgs) { 529ac68637bSLei Zhang auto err = formatv("op '{0}' argument number mismatch: " 53004b6d2f3SLei Zhang "{1} in pattern vs. {2} in definition", 531ac68637bSLei Zhang op.getOperationName(), numTreeArgs, numOpArgs); 532ac68637bSLei Zhang PrintFatalError(def.getLoc(), err); 53304b6d2f3SLei Zhang } 53404b6d2f3SLei Zhang 53504b6d2f3SLei Zhang // The name attached to the DAG node's operator is for representing the 53604b6d2f3SLei Zhang // results generated from this op. It should be remembered as bound results. 537ac68637bSLei Zhang if (!treeName.empty()) { 538*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() 539*1358df19SLei Zhang << "found symbol bound to op result: " << treeName << '\n'); 540ac68637bSLei Zhang if (!infoMap.bindOpResult(treeName, op)) 541ac68637bSLei Zhang PrintFatalError(def.getLoc(), 542ac68637bSLei Zhang formatv("symbol '{0}' bound more than once", treeName)); 543ac68637bSLei Zhang } 54404b6d2f3SLei Zhang 5452fe8ae4fSJacques Pienaar for (int i = 0; i != numTreeArgs; ++i) { 54604b6d2f3SLei Zhang if (auto treeArg = tree.getArgAsNestedDag(i)) { 54704b6d2f3SLei Zhang // This DAG node argument is a DAG node itself. Go inside recursively. 548ac68637bSLei Zhang collectBoundSymbols(treeArg, infoMap, isSrcPattern); 549e032d0dcSLei Zhang } else if (isSrcPattern) { 550e032d0dcSLei Zhang // We can only bind symbols to op arguments in source pattern. Those 551e032d0dcSLei Zhang // symbols are referenced in result patterns. 55204b6d2f3SLei Zhang auto treeArgName = tree.getArgName(i); 553ac68637bSLei Zhang if (!treeArgName.empty()) { 554*1358df19SLei Zhang LLVM_DEBUG(llvm::dbgs() << "found symbol bound to op argument: " 555*1358df19SLei Zhang << treeArgName << '\n'); 556ac68637bSLei Zhang if (!infoMap.bindOpArgument(treeArgName, op, i)) { 557ac68637bSLei Zhang auto err = formatv("symbol '{0}' bound more than once", treeArgName); 558ac68637bSLei Zhang PrintFatalError(def.getLoc(), err); 559ac68637bSLei Zhang } 560ac68637bSLei Zhang } 56104b6d2f3SLei Zhang } 56204b6d2f3SLei Zhang } 56304b6d2f3SLei Zhang } 564