1*0fca6ea1SDimitry Andric //===- GlobalISelMatchTable.cpp -------------------------------------------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric 9*0fca6ea1SDimitry Andric #include "GlobalISelMatchTable.h" 10*0fca6ea1SDimitry Andric #include "Common/CodeGenInstruction.h" 11*0fca6ea1SDimitry Andric #include "Common/CodeGenRegisters.h" 12*0fca6ea1SDimitry Andric #include "llvm/ADT/Statistic.h" 13*0fca6ea1SDimitry Andric #include "llvm/Support/Debug.h" 14*0fca6ea1SDimitry Andric #include "llvm/Support/LEB128.h" 15*0fca6ea1SDimitry Andric #include "llvm/Support/ScopedPrinter.h" 16*0fca6ea1SDimitry Andric #include "llvm/Support/raw_ostream.h" 17*0fca6ea1SDimitry Andric #include "llvm/TableGen/Error.h" 18*0fca6ea1SDimitry Andric 19*0fca6ea1SDimitry Andric #define DEBUG_TYPE "gi-match-table" 20*0fca6ea1SDimitry Andric 21*0fca6ea1SDimitry Andric STATISTIC(NumPatternEmitted, "Number of patterns emitted"); 22*0fca6ea1SDimitry Andric 23*0fca6ea1SDimitry Andric namespace llvm { 24*0fca6ea1SDimitry Andric namespace gi { 25*0fca6ea1SDimitry Andric 26*0fca6ea1SDimitry Andric namespace { 27*0fca6ea1SDimitry Andric 28*0fca6ea1SDimitry Andric Error failUnsupported(const Twine &Reason) { 29*0fca6ea1SDimitry Andric return make_error<StringError>(Reason, inconvertibleErrorCode()); 30*0fca6ea1SDimitry Andric } 31*0fca6ea1SDimitry Andric 32*0fca6ea1SDimitry Andric /// Get the name of the enum value used to number the predicate function. 33*0fca6ea1SDimitry Andric std::string getEnumNameForPredicate(const TreePredicateFn &Predicate) { 34*0fca6ea1SDimitry Andric if (Predicate.hasGISelPredicateCode()) 35*0fca6ea1SDimitry Andric return "GICXXPred_MI_" + Predicate.getFnName(); 36*0fca6ea1SDimitry Andric return "GICXXPred_" + Predicate.getImmTypeIdentifier().str() + "_" + 37*0fca6ea1SDimitry Andric Predicate.getFnName(); 38*0fca6ea1SDimitry Andric } 39*0fca6ea1SDimitry Andric 40*0fca6ea1SDimitry Andric std::string getMatchOpcodeForImmPredicate(const TreePredicateFn &Predicate) { 41*0fca6ea1SDimitry Andric return "GIM_Check" + Predicate.getImmTypeIdentifier().str() + "ImmPredicate"; 42*0fca6ea1SDimitry Andric } 43*0fca6ea1SDimitry Andric 44*0fca6ea1SDimitry Andric // GIMT_Encode2/4/8 45*0fca6ea1SDimitry Andric constexpr StringLiteral EncodeMacroName = "GIMT_Encode"; 46*0fca6ea1SDimitry Andric 47*0fca6ea1SDimitry Andric } // namespace 48*0fca6ea1SDimitry Andric 49*0fca6ea1SDimitry Andric //===- Helpers ------------------------------------------------------------===// 50*0fca6ea1SDimitry Andric 51*0fca6ea1SDimitry Andric void emitEncodingMacrosDef(raw_ostream &OS) { 52*0fca6ea1SDimitry Andric OS << "#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__\n" 53*0fca6ea1SDimitry Andric << "#define " << EncodeMacroName << "2(Val)" 54*0fca6ea1SDimitry Andric << " uint8_t(Val), uint8_t((uint16_t)Val >> 8)\n" 55*0fca6ea1SDimitry Andric << "#define " << EncodeMacroName << "4(Val)" 56*0fca6ea1SDimitry Andric << " uint8_t(Val), uint8_t((uint32_t)Val >> 8), " 57*0fca6ea1SDimitry Andric "uint8_t((uint32_t)Val >> 16), uint8_t((uint32_t)Val >> 24)\n" 58*0fca6ea1SDimitry Andric << "#define " << EncodeMacroName << "8(Val)" 59*0fca6ea1SDimitry Andric << " uint8_t(Val), uint8_t((uint64_t)Val >> 8), " 60*0fca6ea1SDimitry Andric "uint8_t((uint64_t)Val >> 16), uint8_t((uint64_t)Val >> 24), " 61*0fca6ea1SDimitry Andric "uint8_t((uint64_t)Val >> 32), uint8_t((uint64_t)Val >> 40), " 62*0fca6ea1SDimitry Andric "uint8_t((uint64_t)Val >> 48), uint8_t((uint64_t)Val >> 56)\n" 63*0fca6ea1SDimitry Andric << "#else\n" 64*0fca6ea1SDimitry Andric << "#define " << EncodeMacroName << "2(Val)" 65*0fca6ea1SDimitry Andric << " uint8_t((uint16_t)Val >> 8), uint8_t(Val)\n" 66*0fca6ea1SDimitry Andric << "#define " << EncodeMacroName << "4(Val)" 67*0fca6ea1SDimitry Andric << " uint8_t((uint32_t)Val >> 24), uint8_t((uint32_t)Val >> 16), " 68*0fca6ea1SDimitry Andric "uint8_t((uint32_t)Val >> 8), uint8_t(Val)\n" 69*0fca6ea1SDimitry Andric << "#define " << EncodeMacroName << "8(Val)" 70*0fca6ea1SDimitry Andric << " uint8_t((uint64_t)Val >> 56), uint8_t((uint64_t)Val >> 48), " 71*0fca6ea1SDimitry Andric "uint8_t((uint64_t)Val >> 40), uint8_t((uint64_t)Val >> 32), " 72*0fca6ea1SDimitry Andric "uint8_t((uint64_t)Val >> 24), uint8_t((uint64_t)Val >> 16), " 73*0fca6ea1SDimitry Andric "uint8_t((uint64_t)Val >> 8), uint8_t(Val)\n" 74*0fca6ea1SDimitry Andric << "#endif\n"; 75*0fca6ea1SDimitry Andric } 76*0fca6ea1SDimitry Andric 77*0fca6ea1SDimitry Andric void emitEncodingMacrosUndef(raw_ostream &OS) { 78*0fca6ea1SDimitry Andric OS << "#undef " << EncodeMacroName << "2\n" 79*0fca6ea1SDimitry Andric << "#undef " << EncodeMacroName << "4\n" 80*0fca6ea1SDimitry Andric << "#undef " << EncodeMacroName << "8\n"; 81*0fca6ea1SDimitry Andric } 82*0fca6ea1SDimitry Andric 83*0fca6ea1SDimitry Andric std::string getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset, 84*0fca6ea1SDimitry Andric int HwModeIdx) { 85*0fca6ea1SDimitry Andric std::string Name = "GIFBS"; 86*0fca6ea1SDimitry Andric for (const auto &Feature : FeatureBitset) 87*0fca6ea1SDimitry Andric Name += ("_" + Feature->getName()).str(); 88*0fca6ea1SDimitry Andric if (HwModeIdx >= 0) 89*0fca6ea1SDimitry Andric Name += ("_HwMode" + std::to_string(HwModeIdx)); 90*0fca6ea1SDimitry Andric return Name; 91*0fca6ea1SDimitry Andric } 92*0fca6ea1SDimitry Andric 93*0fca6ea1SDimitry Andric template <class GroupT> 94*0fca6ea1SDimitry Andric std::vector<Matcher *> 95*0fca6ea1SDimitry Andric optimizeRules(ArrayRef<Matcher *> Rules, 96*0fca6ea1SDimitry Andric std::vector<std::unique_ptr<Matcher>> &MatcherStorage) { 97*0fca6ea1SDimitry Andric 98*0fca6ea1SDimitry Andric std::vector<Matcher *> OptRules; 99*0fca6ea1SDimitry Andric std::unique_ptr<GroupT> CurrentGroup = std::make_unique<GroupT>(); 100*0fca6ea1SDimitry Andric assert(CurrentGroup->empty() && "Newly created group isn't empty!"); 101*0fca6ea1SDimitry Andric unsigned NumGroups = 0; 102*0fca6ea1SDimitry Andric 103*0fca6ea1SDimitry Andric auto ProcessCurrentGroup = [&]() { 104*0fca6ea1SDimitry Andric if (CurrentGroup->empty()) 105*0fca6ea1SDimitry Andric // An empty group is good to be reused: 106*0fca6ea1SDimitry Andric return; 107*0fca6ea1SDimitry Andric 108*0fca6ea1SDimitry Andric // If the group isn't large enough to provide any benefit, move all the 109*0fca6ea1SDimitry Andric // added rules out of it and make sure to re-create the group to properly 110*0fca6ea1SDimitry Andric // re-initialize it: 111*0fca6ea1SDimitry Andric if (CurrentGroup->size() < 2) 112*0fca6ea1SDimitry Andric append_range(OptRules, CurrentGroup->matchers()); 113*0fca6ea1SDimitry Andric else { 114*0fca6ea1SDimitry Andric CurrentGroup->finalize(); 115*0fca6ea1SDimitry Andric OptRules.push_back(CurrentGroup.get()); 116*0fca6ea1SDimitry Andric MatcherStorage.emplace_back(std::move(CurrentGroup)); 117*0fca6ea1SDimitry Andric ++NumGroups; 118*0fca6ea1SDimitry Andric } 119*0fca6ea1SDimitry Andric CurrentGroup = std::make_unique<GroupT>(); 120*0fca6ea1SDimitry Andric }; 121*0fca6ea1SDimitry Andric for (Matcher *Rule : Rules) { 122*0fca6ea1SDimitry Andric // Greedily add as many matchers as possible to the current group: 123*0fca6ea1SDimitry Andric if (CurrentGroup->addMatcher(*Rule)) 124*0fca6ea1SDimitry Andric continue; 125*0fca6ea1SDimitry Andric 126*0fca6ea1SDimitry Andric ProcessCurrentGroup(); 127*0fca6ea1SDimitry Andric assert(CurrentGroup->empty() && "A group wasn't properly re-initialized"); 128*0fca6ea1SDimitry Andric 129*0fca6ea1SDimitry Andric // Try to add the pending matcher to a newly created empty group: 130*0fca6ea1SDimitry Andric if (!CurrentGroup->addMatcher(*Rule)) 131*0fca6ea1SDimitry Andric // If we couldn't add the matcher to an empty group, that group type 132*0fca6ea1SDimitry Andric // doesn't support that kind of matchers at all, so just skip it: 133*0fca6ea1SDimitry Andric OptRules.push_back(Rule); 134*0fca6ea1SDimitry Andric } 135*0fca6ea1SDimitry Andric ProcessCurrentGroup(); 136*0fca6ea1SDimitry Andric 137*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "NumGroups: " << NumGroups << "\n"); 138*0fca6ea1SDimitry Andric (void)NumGroups; 139*0fca6ea1SDimitry Andric assert(CurrentGroup->empty() && "The last group wasn't properly processed"); 140*0fca6ea1SDimitry Andric return OptRules; 141*0fca6ea1SDimitry Andric } 142*0fca6ea1SDimitry Andric 143*0fca6ea1SDimitry Andric template std::vector<Matcher *> optimizeRules<GroupMatcher>( 144*0fca6ea1SDimitry Andric ArrayRef<Matcher *> Rules, 145*0fca6ea1SDimitry Andric std::vector<std::unique_ptr<Matcher>> &MatcherStorage); 146*0fca6ea1SDimitry Andric 147*0fca6ea1SDimitry Andric template std::vector<Matcher *> optimizeRules<SwitchMatcher>( 148*0fca6ea1SDimitry Andric ArrayRef<Matcher *> Rules, 149*0fca6ea1SDimitry Andric std::vector<std::unique_ptr<Matcher>> &MatcherStorage); 150*0fca6ea1SDimitry Andric 151*0fca6ea1SDimitry Andric static std::string getEncodedEmitStr(StringRef NamedValue, unsigned NumBytes) { 152*0fca6ea1SDimitry Andric if (NumBytes == 2 || NumBytes == 4 || NumBytes == 8) 153*0fca6ea1SDimitry Andric return (EncodeMacroName + Twine(NumBytes) + "(" + NamedValue + ")").str(); 154*0fca6ea1SDimitry Andric llvm_unreachable("Unsupported number of bytes!"); 155*0fca6ea1SDimitry Andric } 156*0fca6ea1SDimitry Andric 157*0fca6ea1SDimitry Andric //===- Global Data --------------------------------------------------------===// 158*0fca6ea1SDimitry Andric 159*0fca6ea1SDimitry Andric std::set<LLTCodeGen> KnownTypes; 160*0fca6ea1SDimitry Andric 161*0fca6ea1SDimitry Andric //===- MatchTableRecord ---------------------------------------------------===// 162*0fca6ea1SDimitry Andric 163*0fca6ea1SDimitry Andric void MatchTableRecord::emit(raw_ostream &OS, bool LineBreakIsNextAfterThis, 164*0fca6ea1SDimitry Andric const MatchTable &Table) const { 165*0fca6ea1SDimitry Andric bool UseLineComment = 166*0fca6ea1SDimitry Andric LineBreakIsNextAfterThis || (Flags & MTRF_LineBreakFollows); 167*0fca6ea1SDimitry Andric if (Flags & (MTRF_JumpTarget | MTRF_CommaFollows)) 168*0fca6ea1SDimitry Andric UseLineComment = false; 169*0fca6ea1SDimitry Andric 170*0fca6ea1SDimitry Andric if (Flags & MTRF_Comment) 171*0fca6ea1SDimitry Andric OS << (UseLineComment ? "// " : "/*"); 172*0fca6ea1SDimitry Andric 173*0fca6ea1SDimitry Andric if (NumElements > 1 && !(Flags & (MTRF_PreEncoded | MTRF_Comment))) 174*0fca6ea1SDimitry Andric OS << getEncodedEmitStr(EmitStr, NumElements); 175*0fca6ea1SDimitry Andric else 176*0fca6ea1SDimitry Andric OS << EmitStr; 177*0fca6ea1SDimitry Andric 178*0fca6ea1SDimitry Andric if (Flags & MTRF_Label) 179*0fca6ea1SDimitry Andric OS << ": @" << Table.getLabelIndex(LabelID); 180*0fca6ea1SDimitry Andric 181*0fca6ea1SDimitry Andric if ((Flags & MTRF_Comment) && !UseLineComment) 182*0fca6ea1SDimitry Andric OS << "*/"; 183*0fca6ea1SDimitry Andric 184*0fca6ea1SDimitry Andric if (Flags & MTRF_JumpTarget) { 185*0fca6ea1SDimitry Andric if (Flags & MTRF_Comment) 186*0fca6ea1SDimitry Andric OS << " "; 187*0fca6ea1SDimitry Andric // TODO: Could encode this AOT to speed up build of generated file 188*0fca6ea1SDimitry Andric OS << getEncodedEmitStr(llvm::to_string(Table.getLabelIndex(LabelID)), 189*0fca6ea1SDimitry Andric NumElements); 190*0fca6ea1SDimitry Andric } 191*0fca6ea1SDimitry Andric 192*0fca6ea1SDimitry Andric if (Flags & MTRF_CommaFollows) { 193*0fca6ea1SDimitry Andric OS << ","; 194*0fca6ea1SDimitry Andric if (!LineBreakIsNextAfterThis && !(Flags & MTRF_LineBreakFollows)) 195*0fca6ea1SDimitry Andric OS << " "; 196*0fca6ea1SDimitry Andric } 197*0fca6ea1SDimitry Andric 198*0fca6ea1SDimitry Andric if (Flags & MTRF_LineBreakFollows) 199*0fca6ea1SDimitry Andric OS << "\n"; 200*0fca6ea1SDimitry Andric } 201*0fca6ea1SDimitry Andric 202*0fca6ea1SDimitry Andric //===- MatchTable ---------------------------------------------------------===// 203*0fca6ea1SDimitry Andric 204*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::LineBreak = { 205*0fca6ea1SDimitry Andric std::nullopt, "" /* Emit String */, 0 /* Elements */, 206*0fca6ea1SDimitry Andric MatchTableRecord::MTRF_LineBreakFollows}; 207*0fca6ea1SDimitry Andric 208*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::Comment(StringRef Comment) { 209*0fca6ea1SDimitry Andric return MatchTableRecord(std::nullopt, Comment, 0, 210*0fca6ea1SDimitry Andric MatchTableRecord::MTRF_Comment); 211*0fca6ea1SDimitry Andric } 212*0fca6ea1SDimitry Andric 213*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::Opcode(StringRef Opcode, int IndentAdjust) { 214*0fca6ea1SDimitry Andric unsigned ExtraFlags = 0; 215*0fca6ea1SDimitry Andric if (IndentAdjust > 0) 216*0fca6ea1SDimitry Andric ExtraFlags |= MatchTableRecord::MTRF_Indent; 217*0fca6ea1SDimitry Andric if (IndentAdjust < 0) 218*0fca6ea1SDimitry Andric ExtraFlags |= MatchTableRecord::MTRF_Outdent; 219*0fca6ea1SDimitry Andric 220*0fca6ea1SDimitry Andric return MatchTableRecord(std::nullopt, Opcode, 1, 221*0fca6ea1SDimitry Andric MatchTableRecord::MTRF_CommaFollows | ExtraFlags); 222*0fca6ea1SDimitry Andric } 223*0fca6ea1SDimitry Andric 224*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::NamedValue(unsigned NumBytes, 225*0fca6ea1SDimitry Andric StringRef NamedValue) { 226*0fca6ea1SDimitry Andric return MatchTableRecord(std::nullopt, NamedValue, NumBytes, 227*0fca6ea1SDimitry Andric MatchTableRecord::MTRF_CommaFollows); 228*0fca6ea1SDimitry Andric } 229*0fca6ea1SDimitry Andric 230*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::NamedValue(unsigned NumBytes, StringRef NamedValue, 231*0fca6ea1SDimitry Andric int64_t RawValue) { 232*0fca6ea1SDimitry Andric return MatchTableRecord(std::nullopt, NamedValue, NumBytes, 233*0fca6ea1SDimitry Andric MatchTableRecord::MTRF_CommaFollows, RawValue); 234*0fca6ea1SDimitry Andric } 235*0fca6ea1SDimitry Andric 236*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::NamedValue(unsigned NumBytes, StringRef Namespace, 237*0fca6ea1SDimitry Andric StringRef NamedValue) { 238*0fca6ea1SDimitry Andric return MatchTableRecord(std::nullopt, (Namespace + "::" + NamedValue).str(), 239*0fca6ea1SDimitry Andric NumBytes, MatchTableRecord::MTRF_CommaFollows); 240*0fca6ea1SDimitry Andric } 241*0fca6ea1SDimitry Andric 242*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::NamedValue(unsigned NumBytes, StringRef Namespace, 243*0fca6ea1SDimitry Andric StringRef NamedValue, 244*0fca6ea1SDimitry Andric int64_t RawValue) { 245*0fca6ea1SDimitry Andric return MatchTableRecord(std::nullopt, (Namespace + "::" + NamedValue).str(), 246*0fca6ea1SDimitry Andric NumBytes, MatchTableRecord::MTRF_CommaFollows, 247*0fca6ea1SDimitry Andric RawValue); 248*0fca6ea1SDimitry Andric } 249*0fca6ea1SDimitry Andric 250*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::IntValue(unsigned NumBytes, int64_t IntValue) { 251*0fca6ea1SDimitry Andric assert(isUIntN(NumBytes * 8, IntValue) || isIntN(NumBytes * 8, IntValue)); 252*0fca6ea1SDimitry Andric auto Str = llvm::to_string(IntValue); 253*0fca6ea1SDimitry Andric if (NumBytes == 1 && IntValue < 0) 254*0fca6ea1SDimitry Andric Str = "uint8_t(" + Str + ")"; 255*0fca6ea1SDimitry Andric // TODO: Could optimize this directly to save the compiler some work when 256*0fca6ea1SDimitry Andric // building the file 257*0fca6ea1SDimitry Andric return MatchTableRecord(std::nullopt, Str, NumBytes, 258*0fca6ea1SDimitry Andric MatchTableRecord::MTRF_CommaFollows); 259*0fca6ea1SDimitry Andric } 260*0fca6ea1SDimitry Andric 261*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::ULEB128Value(uint64_t IntValue) { 262*0fca6ea1SDimitry Andric uint8_t Buffer[10]; 263*0fca6ea1SDimitry Andric unsigned Len = encodeULEB128(IntValue, Buffer); 264*0fca6ea1SDimitry Andric 265*0fca6ea1SDimitry Andric // Simple case (most common) 266*0fca6ea1SDimitry Andric if (Len == 1) { 267*0fca6ea1SDimitry Andric return MatchTableRecord(std::nullopt, llvm::to_string((unsigned)Buffer[0]), 268*0fca6ea1SDimitry Andric 1, MatchTableRecord::MTRF_CommaFollows); 269*0fca6ea1SDimitry Andric } 270*0fca6ea1SDimitry Andric 271*0fca6ea1SDimitry Andric // Print it as, e.g. /* -123456 (*/, 0xC0, 0xBB, 0x78 /*)*/ 272*0fca6ea1SDimitry Andric std::string Str; 273*0fca6ea1SDimitry Andric raw_string_ostream OS(Str); 274*0fca6ea1SDimitry Andric OS << "/* " << llvm::to_string(IntValue) << "(*/"; 275*0fca6ea1SDimitry Andric for (unsigned K = 0; K < Len; ++K) { 276*0fca6ea1SDimitry Andric if (K) 277*0fca6ea1SDimitry Andric OS << ", "; 278*0fca6ea1SDimitry Andric OS << "0x" << llvm::toHex({Buffer[K]}); 279*0fca6ea1SDimitry Andric } 280*0fca6ea1SDimitry Andric OS << "/*)*/"; 281*0fca6ea1SDimitry Andric return MatchTableRecord(std::nullopt, Str, Len, 282*0fca6ea1SDimitry Andric MatchTableRecord::MTRF_CommaFollows | 283*0fca6ea1SDimitry Andric MatchTableRecord::MTRF_PreEncoded); 284*0fca6ea1SDimitry Andric } 285*0fca6ea1SDimitry Andric 286*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::Label(unsigned LabelID) { 287*0fca6ea1SDimitry Andric return MatchTableRecord(LabelID, "Label " + llvm::to_string(LabelID), 0, 288*0fca6ea1SDimitry Andric MatchTableRecord::MTRF_Label | 289*0fca6ea1SDimitry Andric MatchTableRecord::MTRF_Comment | 290*0fca6ea1SDimitry Andric MatchTableRecord::MTRF_LineBreakFollows); 291*0fca6ea1SDimitry Andric } 292*0fca6ea1SDimitry Andric 293*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::JumpTarget(unsigned LabelID) { 294*0fca6ea1SDimitry Andric return MatchTableRecord(LabelID, "Label " + llvm::to_string(LabelID), 4, 295*0fca6ea1SDimitry Andric MatchTableRecord::MTRF_JumpTarget | 296*0fca6ea1SDimitry Andric MatchTableRecord::MTRF_Comment | 297*0fca6ea1SDimitry Andric MatchTableRecord::MTRF_CommaFollows); 298*0fca6ea1SDimitry Andric } 299*0fca6ea1SDimitry Andric 300*0fca6ea1SDimitry Andric void MatchTable::emitUse(raw_ostream &OS) const { OS << "MatchTable" << ID; } 301*0fca6ea1SDimitry Andric 302*0fca6ea1SDimitry Andric void MatchTable::emitDeclaration(raw_ostream &OS) const { 303*0fca6ea1SDimitry Andric unsigned Indentation = 4; 304*0fca6ea1SDimitry Andric OS << " constexpr static uint8_t MatchTable" << ID << "[] = {"; 305*0fca6ea1SDimitry Andric LineBreak.emit(OS, true, *this); 306*0fca6ea1SDimitry Andric OS << std::string(Indentation, ' '); 307*0fca6ea1SDimitry Andric 308*0fca6ea1SDimitry Andric for (auto I = Contents.begin(), E = Contents.end(); I != E; ++I) { 309*0fca6ea1SDimitry Andric bool LineBreakIsNext = false; 310*0fca6ea1SDimitry Andric const auto &NextI = std::next(I); 311*0fca6ea1SDimitry Andric 312*0fca6ea1SDimitry Andric if (NextI != E) { 313*0fca6ea1SDimitry Andric if (NextI->EmitStr == "" && 314*0fca6ea1SDimitry Andric NextI->Flags == MatchTableRecord::MTRF_LineBreakFollows) 315*0fca6ea1SDimitry Andric LineBreakIsNext = true; 316*0fca6ea1SDimitry Andric } 317*0fca6ea1SDimitry Andric 318*0fca6ea1SDimitry Andric if (I->Flags & MatchTableRecord::MTRF_Indent) 319*0fca6ea1SDimitry Andric Indentation += 2; 320*0fca6ea1SDimitry Andric 321*0fca6ea1SDimitry Andric I->emit(OS, LineBreakIsNext, *this); 322*0fca6ea1SDimitry Andric if (I->Flags & MatchTableRecord::MTRF_LineBreakFollows) 323*0fca6ea1SDimitry Andric OS << std::string(Indentation, ' '); 324*0fca6ea1SDimitry Andric 325*0fca6ea1SDimitry Andric if (I->Flags & MatchTableRecord::MTRF_Outdent) 326*0fca6ea1SDimitry Andric Indentation -= 2; 327*0fca6ea1SDimitry Andric } 328*0fca6ea1SDimitry Andric OS << "}; // Size: " << CurrentSize << " bytes\n"; 329*0fca6ea1SDimitry Andric } 330*0fca6ea1SDimitry Andric 331*0fca6ea1SDimitry Andric MatchTable MatchTable::buildTable(ArrayRef<Matcher *> Rules, bool WithCoverage, 332*0fca6ea1SDimitry Andric bool IsCombiner) { 333*0fca6ea1SDimitry Andric MatchTable Table(WithCoverage, IsCombiner); 334*0fca6ea1SDimitry Andric for (Matcher *Rule : Rules) 335*0fca6ea1SDimitry Andric Rule->emit(Table); 336*0fca6ea1SDimitry Andric 337*0fca6ea1SDimitry Andric return Table << MatchTable::Opcode("GIM_Reject") << MatchTable::LineBreak; 338*0fca6ea1SDimitry Andric } 339*0fca6ea1SDimitry Andric 340*0fca6ea1SDimitry Andric //===- LLTCodeGen ---------------------------------------------------------===// 341*0fca6ea1SDimitry Andric 342*0fca6ea1SDimitry Andric std::string LLTCodeGen::getCxxEnumValue() const { 343*0fca6ea1SDimitry Andric std::string Str; 344*0fca6ea1SDimitry Andric raw_string_ostream OS(Str); 345*0fca6ea1SDimitry Andric 346*0fca6ea1SDimitry Andric emitCxxEnumValue(OS); 347*0fca6ea1SDimitry Andric return Str; 348*0fca6ea1SDimitry Andric } 349*0fca6ea1SDimitry Andric 350*0fca6ea1SDimitry Andric void LLTCodeGen::emitCxxEnumValue(raw_ostream &OS) const { 351*0fca6ea1SDimitry Andric if (Ty.isScalar()) { 352*0fca6ea1SDimitry Andric OS << "GILLT_s" << Ty.getSizeInBits(); 353*0fca6ea1SDimitry Andric return; 354*0fca6ea1SDimitry Andric } 355*0fca6ea1SDimitry Andric if (Ty.isVector()) { 356*0fca6ea1SDimitry Andric OS << (Ty.isScalable() ? "GILLT_nxv" : "GILLT_v") 357*0fca6ea1SDimitry Andric << Ty.getElementCount().getKnownMinValue() << "s" 358*0fca6ea1SDimitry Andric << Ty.getScalarSizeInBits(); 359*0fca6ea1SDimitry Andric return; 360*0fca6ea1SDimitry Andric } 361*0fca6ea1SDimitry Andric if (Ty.isPointer()) { 362*0fca6ea1SDimitry Andric OS << "GILLT_p" << Ty.getAddressSpace(); 363*0fca6ea1SDimitry Andric if (Ty.getSizeInBits() > 0) 364*0fca6ea1SDimitry Andric OS << "s" << Ty.getSizeInBits(); 365*0fca6ea1SDimitry Andric return; 366*0fca6ea1SDimitry Andric } 367*0fca6ea1SDimitry Andric llvm_unreachable("Unhandled LLT"); 368*0fca6ea1SDimitry Andric } 369*0fca6ea1SDimitry Andric 370*0fca6ea1SDimitry Andric void LLTCodeGen::emitCxxConstructorCall(raw_ostream &OS) const { 371*0fca6ea1SDimitry Andric if (Ty.isScalar()) { 372*0fca6ea1SDimitry Andric OS << "LLT::scalar(" << Ty.getSizeInBits() << ")"; 373*0fca6ea1SDimitry Andric return; 374*0fca6ea1SDimitry Andric } 375*0fca6ea1SDimitry Andric if (Ty.isVector()) { 376*0fca6ea1SDimitry Andric OS << "LLT::vector(" 377*0fca6ea1SDimitry Andric << (Ty.isScalable() ? "ElementCount::getScalable(" 378*0fca6ea1SDimitry Andric : "ElementCount::getFixed(") 379*0fca6ea1SDimitry Andric << Ty.getElementCount().getKnownMinValue() << "), " 380*0fca6ea1SDimitry Andric << Ty.getScalarSizeInBits() << ")"; 381*0fca6ea1SDimitry Andric return; 382*0fca6ea1SDimitry Andric } 383*0fca6ea1SDimitry Andric if (Ty.isPointer() && Ty.getSizeInBits() > 0) { 384*0fca6ea1SDimitry Andric OS << "LLT::pointer(" << Ty.getAddressSpace() << ", " << Ty.getSizeInBits() 385*0fca6ea1SDimitry Andric << ")"; 386*0fca6ea1SDimitry Andric return; 387*0fca6ea1SDimitry Andric } 388*0fca6ea1SDimitry Andric llvm_unreachable("Unhandled LLT"); 389*0fca6ea1SDimitry Andric } 390*0fca6ea1SDimitry Andric 391*0fca6ea1SDimitry Andric /// This ordering is used for std::unique() and llvm::sort(). There's no 392*0fca6ea1SDimitry Andric /// particular logic behind the order but either A < B or B < A must be 393*0fca6ea1SDimitry Andric /// true if A != B. 394*0fca6ea1SDimitry Andric bool LLTCodeGen::operator<(const LLTCodeGen &Other) const { 395*0fca6ea1SDimitry Andric if (Ty.isValid() != Other.Ty.isValid()) 396*0fca6ea1SDimitry Andric return Ty.isValid() < Other.Ty.isValid(); 397*0fca6ea1SDimitry Andric if (!Ty.isValid()) 398*0fca6ea1SDimitry Andric return false; 399*0fca6ea1SDimitry Andric 400*0fca6ea1SDimitry Andric if (Ty.isVector() != Other.Ty.isVector()) 401*0fca6ea1SDimitry Andric return Ty.isVector() < Other.Ty.isVector(); 402*0fca6ea1SDimitry Andric if (Ty.isScalar() != Other.Ty.isScalar()) 403*0fca6ea1SDimitry Andric return Ty.isScalar() < Other.Ty.isScalar(); 404*0fca6ea1SDimitry Andric if (Ty.isPointer() != Other.Ty.isPointer()) 405*0fca6ea1SDimitry Andric return Ty.isPointer() < Other.Ty.isPointer(); 406*0fca6ea1SDimitry Andric 407*0fca6ea1SDimitry Andric if (Ty.isPointer() && Ty.getAddressSpace() != Other.Ty.getAddressSpace()) 408*0fca6ea1SDimitry Andric return Ty.getAddressSpace() < Other.Ty.getAddressSpace(); 409*0fca6ea1SDimitry Andric 410*0fca6ea1SDimitry Andric if (Ty.isVector() && Ty.getElementCount() != Other.Ty.getElementCount()) 411*0fca6ea1SDimitry Andric return std::tuple(Ty.isScalable(), 412*0fca6ea1SDimitry Andric Ty.getElementCount().getKnownMinValue()) < 413*0fca6ea1SDimitry Andric std::tuple(Other.Ty.isScalable(), 414*0fca6ea1SDimitry Andric Other.Ty.getElementCount().getKnownMinValue()); 415*0fca6ea1SDimitry Andric 416*0fca6ea1SDimitry Andric assert((!Ty.isVector() || Ty.isScalable() == Other.Ty.isScalable()) && 417*0fca6ea1SDimitry Andric "Unexpected mismatch of scalable property"); 418*0fca6ea1SDimitry Andric return Ty.isVector() 419*0fca6ea1SDimitry Andric ? std::tuple(Ty.isScalable(), 420*0fca6ea1SDimitry Andric Ty.getSizeInBits().getKnownMinValue()) < 421*0fca6ea1SDimitry Andric std::tuple(Other.Ty.isScalable(), 422*0fca6ea1SDimitry Andric Other.Ty.getSizeInBits().getKnownMinValue()) 423*0fca6ea1SDimitry Andric : Ty.getSizeInBits().getFixedValue() < 424*0fca6ea1SDimitry Andric Other.Ty.getSizeInBits().getFixedValue(); 425*0fca6ea1SDimitry Andric } 426*0fca6ea1SDimitry Andric 427*0fca6ea1SDimitry Andric //===- LLTCodeGen Helpers -------------------------------------------------===// 428*0fca6ea1SDimitry Andric 429*0fca6ea1SDimitry Andric std::optional<LLTCodeGen> MVTToLLT(MVT::SimpleValueType SVT) { 430*0fca6ea1SDimitry Andric MVT VT(SVT); 431*0fca6ea1SDimitry Andric 432*0fca6ea1SDimitry Andric if (VT.isVector() && !VT.getVectorElementCount().isScalar()) 433*0fca6ea1SDimitry Andric return LLTCodeGen( 434*0fca6ea1SDimitry Andric LLT::vector(VT.getVectorElementCount(), VT.getScalarSizeInBits())); 435*0fca6ea1SDimitry Andric 436*0fca6ea1SDimitry Andric if (VT.isInteger() || VT.isFloatingPoint()) 437*0fca6ea1SDimitry Andric return LLTCodeGen(LLT::scalar(VT.getSizeInBits())); 438*0fca6ea1SDimitry Andric 439*0fca6ea1SDimitry Andric return std::nullopt; 440*0fca6ea1SDimitry Andric } 441*0fca6ea1SDimitry Andric 442*0fca6ea1SDimitry Andric //===- Matcher ------------------------------------------------------------===// 443*0fca6ea1SDimitry Andric 444*0fca6ea1SDimitry Andric void Matcher::optimize() {} 445*0fca6ea1SDimitry Andric 446*0fca6ea1SDimitry Andric Matcher::~Matcher() {} 447*0fca6ea1SDimitry Andric 448*0fca6ea1SDimitry Andric //===- GroupMatcher -------------------------------------------------------===// 449*0fca6ea1SDimitry Andric 450*0fca6ea1SDimitry Andric bool GroupMatcher::candidateConditionMatches( 451*0fca6ea1SDimitry Andric const PredicateMatcher &Predicate) const { 452*0fca6ea1SDimitry Andric 453*0fca6ea1SDimitry Andric if (empty()) { 454*0fca6ea1SDimitry Andric // Sharing predicates for nested instructions is not supported yet as we 455*0fca6ea1SDimitry Andric // currently don't hoist the GIM_RecordInsn's properly, therefore we can 456*0fca6ea1SDimitry Andric // only work on the original root instruction (InsnVarID == 0): 457*0fca6ea1SDimitry Andric if (Predicate.getInsnVarID() != 0) 458*0fca6ea1SDimitry Andric return false; 459*0fca6ea1SDimitry Andric // ... otherwise an empty group can handle any predicate with no specific 460*0fca6ea1SDimitry Andric // requirements: 461*0fca6ea1SDimitry Andric return true; 462*0fca6ea1SDimitry Andric } 463*0fca6ea1SDimitry Andric 464*0fca6ea1SDimitry Andric const Matcher &Representative = **Matchers.begin(); 465*0fca6ea1SDimitry Andric const auto &RepresentativeCondition = Representative.getFirstCondition(); 466*0fca6ea1SDimitry Andric // ... if not empty, the group can only accomodate matchers with the exact 467*0fca6ea1SDimitry Andric // same first condition: 468*0fca6ea1SDimitry Andric return Predicate.isIdentical(RepresentativeCondition); 469*0fca6ea1SDimitry Andric } 470*0fca6ea1SDimitry Andric 471*0fca6ea1SDimitry Andric bool GroupMatcher::addMatcher(Matcher &Candidate) { 472*0fca6ea1SDimitry Andric if (!Candidate.hasFirstCondition()) 473*0fca6ea1SDimitry Andric return false; 474*0fca6ea1SDimitry Andric 475*0fca6ea1SDimitry Andric const PredicateMatcher &Predicate = Candidate.getFirstCondition(); 476*0fca6ea1SDimitry Andric if (!candidateConditionMatches(Predicate)) 477*0fca6ea1SDimitry Andric return false; 478*0fca6ea1SDimitry Andric 479*0fca6ea1SDimitry Andric Matchers.push_back(&Candidate); 480*0fca6ea1SDimitry Andric return true; 481*0fca6ea1SDimitry Andric } 482*0fca6ea1SDimitry Andric 483*0fca6ea1SDimitry Andric void GroupMatcher::finalize() { 484*0fca6ea1SDimitry Andric assert(Conditions.empty() && "Already finalized?"); 485*0fca6ea1SDimitry Andric if (empty()) 486*0fca6ea1SDimitry Andric return; 487*0fca6ea1SDimitry Andric 488*0fca6ea1SDimitry Andric Matcher &FirstRule = **Matchers.begin(); 489*0fca6ea1SDimitry Andric for (;;) { 490*0fca6ea1SDimitry Andric // All the checks are expected to succeed during the first iteration: 491*0fca6ea1SDimitry Andric for (const auto &Rule : Matchers) 492*0fca6ea1SDimitry Andric if (!Rule->hasFirstCondition()) 493*0fca6ea1SDimitry Andric return; 494*0fca6ea1SDimitry Andric const auto &FirstCondition = FirstRule.getFirstCondition(); 495*0fca6ea1SDimitry Andric for (unsigned I = 1, E = Matchers.size(); I < E; ++I) 496*0fca6ea1SDimitry Andric if (!Matchers[I]->getFirstCondition().isIdentical(FirstCondition)) 497*0fca6ea1SDimitry Andric return; 498*0fca6ea1SDimitry Andric 499*0fca6ea1SDimitry Andric Conditions.push_back(FirstRule.popFirstCondition()); 500*0fca6ea1SDimitry Andric for (unsigned I = 1, E = Matchers.size(); I < E; ++I) 501*0fca6ea1SDimitry Andric Matchers[I]->popFirstCondition(); 502*0fca6ea1SDimitry Andric } 503*0fca6ea1SDimitry Andric } 504*0fca6ea1SDimitry Andric 505*0fca6ea1SDimitry Andric void GroupMatcher::emit(MatchTable &Table) { 506*0fca6ea1SDimitry Andric unsigned LabelID = ~0U; 507*0fca6ea1SDimitry Andric if (!Conditions.empty()) { 508*0fca6ea1SDimitry Andric LabelID = Table.allocateLabelID(); 509*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_Try", +1) 510*0fca6ea1SDimitry Andric << MatchTable::Comment("On fail goto") 511*0fca6ea1SDimitry Andric << MatchTable::JumpTarget(LabelID) << MatchTable::LineBreak; 512*0fca6ea1SDimitry Andric } 513*0fca6ea1SDimitry Andric for (auto &Condition : Conditions) 514*0fca6ea1SDimitry Andric Condition->emitPredicateOpcodes( 515*0fca6ea1SDimitry Andric Table, *static_cast<RuleMatcher *>(*Matchers.begin())); 516*0fca6ea1SDimitry Andric 517*0fca6ea1SDimitry Andric for (const auto &M : Matchers) 518*0fca6ea1SDimitry Andric M->emit(Table); 519*0fca6ea1SDimitry Andric 520*0fca6ea1SDimitry Andric // Exit the group 521*0fca6ea1SDimitry Andric if (!Conditions.empty()) 522*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_Reject", -1) << MatchTable::LineBreak 523*0fca6ea1SDimitry Andric << MatchTable::Label(LabelID); 524*0fca6ea1SDimitry Andric } 525*0fca6ea1SDimitry Andric 526*0fca6ea1SDimitry Andric void GroupMatcher::optimize() { 527*0fca6ea1SDimitry Andric // Make sure we only sort by a specific predicate within a range of rules that 528*0fca6ea1SDimitry Andric // all have that predicate checked against a specific value (not a wildcard): 529*0fca6ea1SDimitry Andric auto F = Matchers.begin(); 530*0fca6ea1SDimitry Andric auto T = F; 531*0fca6ea1SDimitry Andric auto E = Matchers.end(); 532*0fca6ea1SDimitry Andric while (T != E) { 533*0fca6ea1SDimitry Andric while (T != E) { 534*0fca6ea1SDimitry Andric auto *R = static_cast<RuleMatcher *>(*T); 535*0fca6ea1SDimitry Andric if (!R->getFirstConditionAsRootType().get().isValid()) 536*0fca6ea1SDimitry Andric break; 537*0fca6ea1SDimitry Andric ++T; 538*0fca6ea1SDimitry Andric } 539*0fca6ea1SDimitry Andric std::stable_sort(F, T, [](Matcher *A, Matcher *B) { 540*0fca6ea1SDimitry Andric auto *L = static_cast<RuleMatcher *>(A); 541*0fca6ea1SDimitry Andric auto *R = static_cast<RuleMatcher *>(B); 542*0fca6ea1SDimitry Andric return L->getFirstConditionAsRootType() < 543*0fca6ea1SDimitry Andric R->getFirstConditionAsRootType(); 544*0fca6ea1SDimitry Andric }); 545*0fca6ea1SDimitry Andric if (T != E) 546*0fca6ea1SDimitry Andric F = ++T; 547*0fca6ea1SDimitry Andric } 548*0fca6ea1SDimitry Andric Matchers = optimizeRules<GroupMatcher>(Matchers, MatcherStorage); 549*0fca6ea1SDimitry Andric Matchers = optimizeRules<SwitchMatcher>(Matchers, MatcherStorage); 550*0fca6ea1SDimitry Andric } 551*0fca6ea1SDimitry Andric 552*0fca6ea1SDimitry Andric //===- SwitchMatcher ------------------------------------------------------===// 553*0fca6ea1SDimitry Andric 554*0fca6ea1SDimitry Andric bool SwitchMatcher::isSupportedPredicateType(const PredicateMatcher &P) { 555*0fca6ea1SDimitry Andric return isa<InstructionOpcodeMatcher>(P) || isa<LLTOperandMatcher>(P); 556*0fca6ea1SDimitry Andric } 557*0fca6ea1SDimitry Andric 558*0fca6ea1SDimitry Andric bool SwitchMatcher::candidateConditionMatches( 559*0fca6ea1SDimitry Andric const PredicateMatcher &Predicate) const { 560*0fca6ea1SDimitry Andric 561*0fca6ea1SDimitry Andric if (empty()) { 562*0fca6ea1SDimitry Andric // Sharing predicates for nested instructions is not supported yet as we 563*0fca6ea1SDimitry Andric // currently don't hoist the GIM_RecordInsn's properly, therefore we can 564*0fca6ea1SDimitry Andric // only work on the original root instruction (InsnVarID == 0): 565*0fca6ea1SDimitry Andric if (Predicate.getInsnVarID() != 0) 566*0fca6ea1SDimitry Andric return false; 567*0fca6ea1SDimitry Andric // ... while an attempt to add even a root matcher to an empty SwitchMatcher 568*0fca6ea1SDimitry Andric // could fail as not all the types of conditions are supported: 569*0fca6ea1SDimitry Andric if (!isSupportedPredicateType(Predicate)) 570*0fca6ea1SDimitry Andric return false; 571*0fca6ea1SDimitry Andric // ... or the condition might not have a proper implementation of 572*0fca6ea1SDimitry Andric // getValue() / isIdenticalDownToValue() yet: 573*0fca6ea1SDimitry Andric if (!Predicate.hasValue()) 574*0fca6ea1SDimitry Andric return false; 575*0fca6ea1SDimitry Andric // ... otherwise an empty Switch can accomodate the condition with no 576*0fca6ea1SDimitry Andric // further requirements: 577*0fca6ea1SDimitry Andric return true; 578*0fca6ea1SDimitry Andric } 579*0fca6ea1SDimitry Andric 580*0fca6ea1SDimitry Andric const Matcher &CaseRepresentative = **Matchers.begin(); 581*0fca6ea1SDimitry Andric const auto &RepresentativeCondition = CaseRepresentative.getFirstCondition(); 582*0fca6ea1SDimitry Andric // Switch-cases must share the same kind of condition and path to the value it 583*0fca6ea1SDimitry Andric // checks: 584*0fca6ea1SDimitry Andric if (!Predicate.isIdenticalDownToValue(RepresentativeCondition)) 585*0fca6ea1SDimitry Andric return false; 586*0fca6ea1SDimitry Andric 587*0fca6ea1SDimitry Andric const auto Value = Predicate.getValue(); 588*0fca6ea1SDimitry Andric // ... but be unique with respect to the actual value they check: 589*0fca6ea1SDimitry Andric return Values.count(Value) == 0; 590*0fca6ea1SDimitry Andric } 591*0fca6ea1SDimitry Andric 592*0fca6ea1SDimitry Andric bool SwitchMatcher::addMatcher(Matcher &Candidate) { 593*0fca6ea1SDimitry Andric if (!Candidate.hasFirstCondition()) 594*0fca6ea1SDimitry Andric return false; 595*0fca6ea1SDimitry Andric 596*0fca6ea1SDimitry Andric const PredicateMatcher &Predicate = Candidate.getFirstCondition(); 597*0fca6ea1SDimitry Andric if (!candidateConditionMatches(Predicate)) 598*0fca6ea1SDimitry Andric return false; 599*0fca6ea1SDimitry Andric const auto Value = Predicate.getValue(); 600*0fca6ea1SDimitry Andric Values.insert(Value); 601*0fca6ea1SDimitry Andric 602*0fca6ea1SDimitry Andric Matchers.push_back(&Candidate); 603*0fca6ea1SDimitry Andric return true; 604*0fca6ea1SDimitry Andric } 605*0fca6ea1SDimitry Andric 606*0fca6ea1SDimitry Andric void SwitchMatcher::finalize() { 607*0fca6ea1SDimitry Andric assert(Condition == nullptr && "Already finalized"); 608*0fca6ea1SDimitry Andric assert(Values.size() == Matchers.size() && "Broken SwitchMatcher"); 609*0fca6ea1SDimitry Andric if (empty()) 610*0fca6ea1SDimitry Andric return; 611*0fca6ea1SDimitry Andric 612*0fca6ea1SDimitry Andric llvm::stable_sort(Matchers, [](const Matcher *L, const Matcher *R) { 613*0fca6ea1SDimitry Andric return L->getFirstCondition().getValue() < 614*0fca6ea1SDimitry Andric R->getFirstCondition().getValue(); 615*0fca6ea1SDimitry Andric }); 616*0fca6ea1SDimitry Andric Condition = Matchers[0]->popFirstCondition(); 617*0fca6ea1SDimitry Andric for (unsigned I = 1, E = Values.size(); I < E; ++I) 618*0fca6ea1SDimitry Andric Matchers[I]->popFirstCondition(); 619*0fca6ea1SDimitry Andric } 620*0fca6ea1SDimitry Andric 621*0fca6ea1SDimitry Andric void SwitchMatcher::emitPredicateSpecificOpcodes(const PredicateMatcher &P, 622*0fca6ea1SDimitry Andric MatchTable &Table) { 623*0fca6ea1SDimitry Andric assert(isSupportedPredicateType(P) && "Predicate type is not supported"); 624*0fca6ea1SDimitry Andric 625*0fca6ea1SDimitry Andric if (const auto *Condition = dyn_cast<InstructionOpcodeMatcher>(&P)) { 626*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_SwitchOpcode") << MatchTable::Comment("MI") 627*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(Condition->getInsnVarID()); 628*0fca6ea1SDimitry Andric return; 629*0fca6ea1SDimitry Andric } 630*0fca6ea1SDimitry Andric if (const auto *Condition = dyn_cast<LLTOperandMatcher>(&P)) { 631*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_SwitchType") << MatchTable::Comment("MI") 632*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(Condition->getInsnVarID()) 633*0fca6ea1SDimitry Andric << MatchTable::Comment("Op") 634*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(Condition->getOpIdx()); 635*0fca6ea1SDimitry Andric return; 636*0fca6ea1SDimitry Andric } 637*0fca6ea1SDimitry Andric 638*0fca6ea1SDimitry Andric llvm_unreachable("emitPredicateSpecificOpcodes is broken: can not handle a " 639*0fca6ea1SDimitry Andric "predicate type that is claimed to be supported"); 640*0fca6ea1SDimitry Andric } 641*0fca6ea1SDimitry Andric 642*0fca6ea1SDimitry Andric void SwitchMatcher::emit(MatchTable &Table) { 643*0fca6ea1SDimitry Andric assert(Values.size() == Matchers.size() && "Broken SwitchMatcher"); 644*0fca6ea1SDimitry Andric if (empty()) 645*0fca6ea1SDimitry Andric return; 646*0fca6ea1SDimitry Andric assert(Condition != nullptr && 647*0fca6ea1SDimitry Andric "Broken SwitchMatcher, hasn't been finalized?"); 648*0fca6ea1SDimitry Andric 649*0fca6ea1SDimitry Andric std::vector<unsigned> LabelIDs(Values.size()); 650*0fca6ea1SDimitry Andric std::generate(LabelIDs.begin(), LabelIDs.end(), 651*0fca6ea1SDimitry Andric [&Table]() { return Table.allocateLabelID(); }); 652*0fca6ea1SDimitry Andric const unsigned Default = Table.allocateLabelID(); 653*0fca6ea1SDimitry Andric 654*0fca6ea1SDimitry Andric const int64_t LowerBound = Values.begin()->getRawValue(); 655*0fca6ea1SDimitry Andric const int64_t UpperBound = Values.rbegin()->getRawValue() + 1; 656*0fca6ea1SDimitry Andric 657*0fca6ea1SDimitry Andric emitPredicateSpecificOpcodes(*Condition, Table); 658*0fca6ea1SDimitry Andric 659*0fca6ea1SDimitry Andric Table << MatchTable::Comment("[") << MatchTable::IntValue(2, LowerBound) 660*0fca6ea1SDimitry Andric << MatchTable::IntValue(2, UpperBound) << MatchTable::Comment(")") 661*0fca6ea1SDimitry Andric << MatchTable::Comment("default:") << MatchTable::JumpTarget(Default); 662*0fca6ea1SDimitry Andric 663*0fca6ea1SDimitry Andric int64_t J = LowerBound; 664*0fca6ea1SDimitry Andric auto VI = Values.begin(); 665*0fca6ea1SDimitry Andric for (unsigned I = 0, E = Values.size(); I < E; ++I) { 666*0fca6ea1SDimitry Andric auto V = *VI++; 667*0fca6ea1SDimitry Andric while (J++ < V.getRawValue()) 668*0fca6ea1SDimitry Andric Table << MatchTable::IntValue(4, 0); 669*0fca6ea1SDimitry Andric V.turnIntoComment(); 670*0fca6ea1SDimitry Andric Table << MatchTable::LineBreak << V << MatchTable::JumpTarget(LabelIDs[I]); 671*0fca6ea1SDimitry Andric } 672*0fca6ea1SDimitry Andric Table << MatchTable::LineBreak; 673*0fca6ea1SDimitry Andric 674*0fca6ea1SDimitry Andric for (unsigned I = 0, E = Values.size(); I < E; ++I) { 675*0fca6ea1SDimitry Andric Table << MatchTable::Label(LabelIDs[I]); 676*0fca6ea1SDimitry Andric Matchers[I]->emit(Table); 677*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_Reject") << MatchTable::LineBreak; 678*0fca6ea1SDimitry Andric } 679*0fca6ea1SDimitry Andric Table << MatchTable::Label(Default); 680*0fca6ea1SDimitry Andric } 681*0fca6ea1SDimitry Andric 682*0fca6ea1SDimitry Andric //===- RuleMatcher --------------------------------------------------------===// 683*0fca6ea1SDimitry Andric 684*0fca6ea1SDimitry Andric uint64_t RuleMatcher::NextRuleID = 0; 685*0fca6ea1SDimitry Andric 686*0fca6ea1SDimitry Andric StringRef RuleMatcher::getOpcode() const { 687*0fca6ea1SDimitry Andric return Matchers.front()->getOpcode(); 688*0fca6ea1SDimitry Andric } 689*0fca6ea1SDimitry Andric 690*0fca6ea1SDimitry Andric unsigned RuleMatcher::getNumOperands() const { 691*0fca6ea1SDimitry Andric return Matchers.front()->getNumOperands(); 692*0fca6ea1SDimitry Andric } 693*0fca6ea1SDimitry Andric 694*0fca6ea1SDimitry Andric LLTCodeGen RuleMatcher::getFirstConditionAsRootType() { 695*0fca6ea1SDimitry Andric InstructionMatcher &InsnMatcher = *Matchers.front(); 696*0fca6ea1SDimitry Andric if (!InsnMatcher.predicates_empty()) 697*0fca6ea1SDimitry Andric if (const auto *TM = 698*0fca6ea1SDimitry Andric dyn_cast<LLTOperandMatcher>(&**InsnMatcher.predicates_begin())) 699*0fca6ea1SDimitry Andric if (TM->getInsnVarID() == 0 && TM->getOpIdx() == 0) 700*0fca6ea1SDimitry Andric return TM->getTy(); 701*0fca6ea1SDimitry Andric return {}; 702*0fca6ea1SDimitry Andric } 703*0fca6ea1SDimitry Andric 704*0fca6ea1SDimitry Andric void RuleMatcher::optimize() { 705*0fca6ea1SDimitry Andric for (auto &Item : InsnVariableIDs) { 706*0fca6ea1SDimitry Andric InstructionMatcher &InsnMatcher = *Item.first; 707*0fca6ea1SDimitry Andric for (auto &OM : InsnMatcher.operands()) { 708*0fca6ea1SDimitry Andric // Complex Patterns are usually expensive and they relatively rarely fail 709*0fca6ea1SDimitry Andric // on their own: more often we end up throwing away all the work done by a 710*0fca6ea1SDimitry Andric // matching part of a complex pattern because some other part of the 711*0fca6ea1SDimitry Andric // enclosing pattern didn't match. All of this makes it beneficial to 712*0fca6ea1SDimitry Andric // delay complex patterns until the very end of the rule matching, 713*0fca6ea1SDimitry Andric // especially for targets having lots of complex patterns. 714*0fca6ea1SDimitry Andric for (auto &OP : OM->predicates()) 715*0fca6ea1SDimitry Andric if (isa<ComplexPatternOperandMatcher>(OP)) 716*0fca6ea1SDimitry Andric EpilogueMatchers.emplace_back(std::move(OP)); 717*0fca6ea1SDimitry Andric OM->eraseNullPredicates(); 718*0fca6ea1SDimitry Andric } 719*0fca6ea1SDimitry Andric InsnMatcher.optimize(); 720*0fca6ea1SDimitry Andric } 721*0fca6ea1SDimitry Andric llvm::sort(EpilogueMatchers, [](const std::unique_ptr<PredicateMatcher> &L, 722*0fca6ea1SDimitry Andric const std::unique_ptr<PredicateMatcher> &R) { 723*0fca6ea1SDimitry Andric return std::tuple(L->getKind(), L->getInsnVarID(), L->getOpIdx()) < 724*0fca6ea1SDimitry Andric std::tuple(R->getKind(), R->getInsnVarID(), R->getOpIdx()); 725*0fca6ea1SDimitry Andric }); 726*0fca6ea1SDimitry Andric 727*0fca6ea1SDimitry Andric // Deduplicate EraseInst actions, and if an EraseInst erases the root, place 728*0fca6ea1SDimitry Andric // it at the end to favor generation of GIR_EraseRootFromParent_Done 729*0fca6ea1SDimitry Andric DenseSet<unsigned> AlreadySeenEraseInsts; 730*0fca6ea1SDimitry Andric auto EraseRootIt = Actions.end(); 731*0fca6ea1SDimitry Andric auto It = Actions.begin(); 732*0fca6ea1SDimitry Andric while (It != Actions.end()) { 733*0fca6ea1SDimitry Andric if (const auto *EI = dyn_cast<EraseInstAction>(It->get())) { 734*0fca6ea1SDimitry Andric unsigned InstID = EI->getInsnID(); 735*0fca6ea1SDimitry Andric if (!AlreadySeenEraseInsts.insert(InstID).second) { 736*0fca6ea1SDimitry Andric It = Actions.erase(It); 737*0fca6ea1SDimitry Andric continue; 738*0fca6ea1SDimitry Andric } 739*0fca6ea1SDimitry Andric 740*0fca6ea1SDimitry Andric if (InstID == 0) 741*0fca6ea1SDimitry Andric EraseRootIt = It; 742*0fca6ea1SDimitry Andric } 743*0fca6ea1SDimitry Andric 744*0fca6ea1SDimitry Andric ++It; 745*0fca6ea1SDimitry Andric } 746*0fca6ea1SDimitry Andric 747*0fca6ea1SDimitry Andric if (EraseRootIt != Actions.end()) 748*0fca6ea1SDimitry Andric Actions.splice(Actions.end(), Actions, EraseRootIt); 749*0fca6ea1SDimitry Andric } 750*0fca6ea1SDimitry Andric 751*0fca6ea1SDimitry Andric bool RuleMatcher::hasFirstCondition() const { 752*0fca6ea1SDimitry Andric if (insnmatchers_empty()) 753*0fca6ea1SDimitry Andric return false; 754*0fca6ea1SDimitry Andric InstructionMatcher &Matcher = insnmatchers_front(); 755*0fca6ea1SDimitry Andric if (!Matcher.predicates_empty()) 756*0fca6ea1SDimitry Andric return true; 757*0fca6ea1SDimitry Andric for (auto &OM : Matcher.operands()) 758*0fca6ea1SDimitry Andric for (auto &OP : OM->predicates()) 759*0fca6ea1SDimitry Andric if (!isa<InstructionOperandMatcher>(OP)) 760*0fca6ea1SDimitry Andric return true; 761*0fca6ea1SDimitry Andric return false; 762*0fca6ea1SDimitry Andric } 763*0fca6ea1SDimitry Andric 764*0fca6ea1SDimitry Andric const PredicateMatcher &RuleMatcher::getFirstCondition() const { 765*0fca6ea1SDimitry Andric assert(!insnmatchers_empty() && 766*0fca6ea1SDimitry Andric "Trying to get a condition from an empty RuleMatcher"); 767*0fca6ea1SDimitry Andric 768*0fca6ea1SDimitry Andric InstructionMatcher &Matcher = insnmatchers_front(); 769*0fca6ea1SDimitry Andric if (!Matcher.predicates_empty()) 770*0fca6ea1SDimitry Andric return **Matcher.predicates_begin(); 771*0fca6ea1SDimitry Andric // If there is no more predicate on the instruction itself, look at its 772*0fca6ea1SDimitry Andric // operands. 773*0fca6ea1SDimitry Andric for (auto &OM : Matcher.operands()) 774*0fca6ea1SDimitry Andric for (auto &OP : OM->predicates()) 775*0fca6ea1SDimitry Andric if (!isa<InstructionOperandMatcher>(OP)) 776*0fca6ea1SDimitry Andric return *OP; 777*0fca6ea1SDimitry Andric 778*0fca6ea1SDimitry Andric llvm_unreachable("Trying to get a condition from an InstructionMatcher with " 779*0fca6ea1SDimitry Andric "no conditions"); 780*0fca6ea1SDimitry Andric } 781*0fca6ea1SDimitry Andric 782*0fca6ea1SDimitry Andric std::unique_ptr<PredicateMatcher> RuleMatcher::popFirstCondition() { 783*0fca6ea1SDimitry Andric assert(!insnmatchers_empty() && 784*0fca6ea1SDimitry Andric "Trying to pop a condition from an empty RuleMatcher"); 785*0fca6ea1SDimitry Andric 786*0fca6ea1SDimitry Andric InstructionMatcher &Matcher = insnmatchers_front(); 787*0fca6ea1SDimitry Andric if (!Matcher.predicates_empty()) 788*0fca6ea1SDimitry Andric return Matcher.predicates_pop_front(); 789*0fca6ea1SDimitry Andric // If there is no more predicate on the instruction itself, look at its 790*0fca6ea1SDimitry Andric // operands. 791*0fca6ea1SDimitry Andric for (auto &OM : Matcher.operands()) 792*0fca6ea1SDimitry Andric for (auto &OP : OM->predicates()) 793*0fca6ea1SDimitry Andric if (!isa<InstructionOperandMatcher>(OP)) { 794*0fca6ea1SDimitry Andric std::unique_ptr<PredicateMatcher> Result = std::move(OP); 795*0fca6ea1SDimitry Andric OM->eraseNullPredicates(); 796*0fca6ea1SDimitry Andric return Result; 797*0fca6ea1SDimitry Andric } 798*0fca6ea1SDimitry Andric 799*0fca6ea1SDimitry Andric llvm_unreachable("Trying to pop a condition from an InstructionMatcher with " 800*0fca6ea1SDimitry Andric "no conditions"); 801*0fca6ea1SDimitry Andric } 802*0fca6ea1SDimitry Andric 803*0fca6ea1SDimitry Andric GISelFlags RuleMatcher::updateGISelFlag(GISelFlags CurFlags, const Record *R, 804*0fca6ea1SDimitry Andric StringRef FlagName, 805*0fca6ea1SDimitry Andric GISelFlags FlagBit) { 806*0fca6ea1SDimitry Andric // If the value of a flag is unset, ignore it. 807*0fca6ea1SDimitry Andric // If it's set, it always takes precedence over the existing value so 808*0fca6ea1SDimitry Andric // clear/set the corresponding bit. 809*0fca6ea1SDimitry Andric bool Unset = false; 810*0fca6ea1SDimitry Andric bool Value = R->getValueAsBitOrUnset("GIIgnoreCopies", Unset); 811*0fca6ea1SDimitry Andric if (!Unset) 812*0fca6ea1SDimitry Andric return Value ? (CurFlags | FlagBit) : (CurFlags & ~FlagBit); 813*0fca6ea1SDimitry Andric return CurFlags; 814*0fca6ea1SDimitry Andric } 815*0fca6ea1SDimitry Andric 816*0fca6ea1SDimitry Andric SaveAndRestore<GISelFlags> RuleMatcher::setGISelFlags(const Record *R) { 817*0fca6ea1SDimitry Andric if (!R || !R->isSubClassOf("GISelFlags")) 818*0fca6ea1SDimitry Andric return {Flags, Flags}; 819*0fca6ea1SDimitry Andric 820*0fca6ea1SDimitry Andric assert((R->isSubClassOf("PatFrags") || R->isSubClassOf("Pattern")) && 821*0fca6ea1SDimitry Andric "GISelFlags is only expected on Pattern/PatFrags!"); 822*0fca6ea1SDimitry Andric 823*0fca6ea1SDimitry Andric GISelFlags NewFlags = 824*0fca6ea1SDimitry Andric updateGISelFlag(Flags, R, "GIIgnoreCopies", GISF_IgnoreCopies); 825*0fca6ea1SDimitry Andric return {Flags, NewFlags}; 826*0fca6ea1SDimitry Andric } 827*0fca6ea1SDimitry Andric 828*0fca6ea1SDimitry Andric Error RuleMatcher::defineComplexSubOperand(StringRef SymbolicName, 829*0fca6ea1SDimitry Andric Record *ComplexPattern, 830*0fca6ea1SDimitry Andric unsigned RendererID, 831*0fca6ea1SDimitry Andric unsigned SubOperandID, 832*0fca6ea1SDimitry Andric StringRef ParentSymbolicName) { 833*0fca6ea1SDimitry Andric std::string ParentName(ParentSymbolicName); 834*0fca6ea1SDimitry Andric if (ComplexSubOperands.count(SymbolicName)) { 835*0fca6ea1SDimitry Andric const std::string &RecordedParentName = 836*0fca6ea1SDimitry Andric ComplexSubOperandsParentName[SymbolicName]; 837*0fca6ea1SDimitry Andric if (RecordedParentName != ParentName) 838*0fca6ea1SDimitry Andric return failUnsupported("Error: Complex suboperand " + SymbolicName + 839*0fca6ea1SDimitry Andric " referenced by different operands: " + 840*0fca6ea1SDimitry Andric RecordedParentName + " and " + ParentName + "."); 841*0fca6ea1SDimitry Andric // Complex suboperand referenced more than once from same the operand is 842*0fca6ea1SDimitry Andric // used to generate 'same operand check'. Emitting of 843*0fca6ea1SDimitry Andric // GIR_ComplexSubOperandRenderer for them is already handled. 844*0fca6ea1SDimitry Andric return Error::success(); 845*0fca6ea1SDimitry Andric } 846*0fca6ea1SDimitry Andric 847*0fca6ea1SDimitry Andric ComplexSubOperands[SymbolicName] = 848*0fca6ea1SDimitry Andric std::tuple(ComplexPattern, RendererID, SubOperandID); 849*0fca6ea1SDimitry Andric ComplexSubOperandsParentName[SymbolicName] = ParentName; 850*0fca6ea1SDimitry Andric 851*0fca6ea1SDimitry Andric return Error::success(); 852*0fca6ea1SDimitry Andric } 853*0fca6ea1SDimitry Andric 854*0fca6ea1SDimitry Andric InstructionMatcher &RuleMatcher::addInstructionMatcher(StringRef SymbolicName) { 855*0fca6ea1SDimitry Andric Matchers.emplace_back(new InstructionMatcher(*this, SymbolicName)); 856*0fca6ea1SDimitry Andric MutatableInsns.insert(Matchers.back().get()); 857*0fca6ea1SDimitry Andric return *Matchers.back(); 858*0fca6ea1SDimitry Andric } 859*0fca6ea1SDimitry Andric 860*0fca6ea1SDimitry Andric void RuleMatcher::addRequiredSimplePredicate(StringRef PredName) { 861*0fca6ea1SDimitry Andric RequiredSimplePredicates.push_back(PredName.str()); 862*0fca6ea1SDimitry Andric } 863*0fca6ea1SDimitry Andric 864*0fca6ea1SDimitry Andric const std::vector<std::string> &RuleMatcher::getRequiredSimplePredicates() { 865*0fca6ea1SDimitry Andric return RequiredSimplePredicates; 866*0fca6ea1SDimitry Andric } 867*0fca6ea1SDimitry Andric 868*0fca6ea1SDimitry Andric void RuleMatcher::addRequiredFeature(Record *Feature) { 869*0fca6ea1SDimitry Andric RequiredFeatures.push_back(Feature); 870*0fca6ea1SDimitry Andric } 871*0fca6ea1SDimitry Andric 872*0fca6ea1SDimitry Andric const std::vector<Record *> &RuleMatcher::getRequiredFeatures() const { 873*0fca6ea1SDimitry Andric return RequiredFeatures; 874*0fca6ea1SDimitry Andric } 875*0fca6ea1SDimitry Andric 876*0fca6ea1SDimitry Andric unsigned RuleMatcher::implicitlyDefineInsnVar(InstructionMatcher &Matcher) { 877*0fca6ea1SDimitry Andric unsigned NewInsnVarID = NextInsnVarID++; 878*0fca6ea1SDimitry Andric InsnVariableIDs[&Matcher] = NewInsnVarID; 879*0fca6ea1SDimitry Andric return NewInsnVarID; 880*0fca6ea1SDimitry Andric } 881*0fca6ea1SDimitry Andric 882*0fca6ea1SDimitry Andric unsigned RuleMatcher::getInsnVarID(InstructionMatcher &InsnMatcher) const { 883*0fca6ea1SDimitry Andric const auto &I = InsnVariableIDs.find(&InsnMatcher); 884*0fca6ea1SDimitry Andric if (I != InsnVariableIDs.end()) 885*0fca6ea1SDimitry Andric return I->second; 886*0fca6ea1SDimitry Andric llvm_unreachable("Matched Insn was not captured in a local variable"); 887*0fca6ea1SDimitry Andric } 888*0fca6ea1SDimitry Andric 889*0fca6ea1SDimitry Andric void RuleMatcher::defineOperand(StringRef SymbolicName, OperandMatcher &OM) { 890*0fca6ea1SDimitry Andric if (!DefinedOperands.contains(SymbolicName)) { 891*0fca6ea1SDimitry Andric DefinedOperands[SymbolicName] = &OM; 892*0fca6ea1SDimitry Andric return; 893*0fca6ea1SDimitry Andric } 894*0fca6ea1SDimitry Andric 895*0fca6ea1SDimitry Andric // If the operand is already defined, then we must ensure both references in 896*0fca6ea1SDimitry Andric // the matcher have the exact same node. 897*0fca6ea1SDimitry Andric RuleMatcher &RM = OM.getInstructionMatcher().getRuleMatcher(); 898*0fca6ea1SDimitry Andric OM.addPredicate<SameOperandMatcher>( 899*0fca6ea1SDimitry Andric OM.getSymbolicName(), getOperandMatcher(OM.getSymbolicName()).getOpIdx(), 900*0fca6ea1SDimitry Andric RM.getGISelFlags()); 901*0fca6ea1SDimitry Andric } 902*0fca6ea1SDimitry Andric 903*0fca6ea1SDimitry Andric void RuleMatcher::definePhysRegOperand(Record *Reg, OperandMatcher &OM) { 904*0fca6ea1SDimitry Andric if (!PhysRegOperands.contains(Reg)) { 905*0fca6ea1SDimitry Andric PhysRegOperands[Reg] = &OM; 906*0fca6ea1SDimitry Andric return; 907*0fca6ea1SDimitry Andric } 908*0fca6ea1SDimitry Andric } 909*0fca6ea1SDimitry Andric 910*0fca6ea1SDimitry Andric InstructionMatcher & 911*0fca6ea1SDimitry Andric RuleMatcher::getInstructionMatcher(StringRef SymbolicName) const { 912*0fca6ea1SDimitry Andric for (const auto &I : InsnVariableIDs) 913*0fca6ea1SDimitry Andric if (I.first->getSymbolicName() == SymbolicName) 914*0fca6ea1SDimitry Andric return *I.first; 915*0fca6ea1SDimitry Andric llvm_unreachable( 916*0fca6ea1SDimitry Andric ("Failed to lookup instruction " + SymbolicName).str().c_str()); 917*0fca6ea1SDimitry Andric } 918*0fca6ea1SDimitry Andric 919*0fca6ea1SDimitry Andric const OperandMatcher &RuleMatcher::getPhysRegOperandMatcher(Record *Reg) const { 920*0fca6ea1SDimitry Andric const auto &I = PhysRegOperands.find(Reg); 921*0fca6ea1SDimitry Andric 922*0fca6ea1SDimitry Andric if (I == PhysRegOperands.end()) { 923*0fca6ea1SDimitry Andric PrintFatalError(SrcLoc, "Register " + Reg->getName() + 924*0fca6ea1SDimitry Andric " was not declared in matcher"); 925*0fca6ea1SDimitry Andric } 926*0fca6ea1SDimitry Andric 927*0fca6ea1SDimitry Andric return *I->second; 928*0fca6ea1SDimitry Andric } 929*0fca6ea1SDimitry Andric 930*0fca6ea1SDimitry Andric OperandMatcher &RuleMatcher::getOperandMatcher(StringRef Name) { 931*0fca6ea1SDimitry Andric const auto &I = DefinedOperands.find(Name); 932*0fca6ea1SDimitry Andric 933*0fca6ea1SDimitry Andric if (I == DefinedOperands.end()) 934*0fca6ea1SDimitry Andric PrintFatalError(SrcLoc, "Operand " + Name + " was not declared in matcher"); 935*0fca6ea1SDimitry Andric 936*0fca6ea1SDimitry Andric return *I->second; 937*0fca6ea1SDimitry Andric } 938*0fca6ea1SDimitry Andric 939*0fca6ea1SDimitry Andric const OperandMatcher &RuleMatcher::getOperandMatcher(StringRef Name) const { 940*0fca6ea1SDimitry Andric const auto &I = DefinedOperands.find(Name); 941*0fca6ea1SDimitry Andric 942*0fca6ea1SDimitry Andric if (I == DefinedOperands.end()) 943*0fca6ea1SDimitry Andric PrintFatalError(SrcLoc, "Operand " + Name + " was not declared in matcher"); 944*0fca6ea1SDimitry Andric 945*0fca6ea1SDimitry Andric return *I->second; 946*0fca6ea1SDimitry Andric } 947*0fca6ea1SDimitry Andric 948*0fca6ea1SDimitry Andric void RuleMatcher::emit(MatchTable &Table) { 949*0fca6ea1SDimitry Andric if (Matchers.empty()) 950*0fca6ea1SDimitry Andric llvm_unreachable("Unexpected empty matcher!"); 951*0fca6ea1SDimitry Andric 952*0fca6ea1SDimitry Andric // The representation supports rules that require multiple roots such as: 953*0fca6ea1SDimitry Andric // %ptr(p0) = ... 954*0fca6ea1SDimitry Andric // %elt0(s32) = G_LOAD %ptr 955*0fca6ea1SDimitry Andric // %1(p0) = G_ADD %ptr, 4 956*0fca6ea1SDimitry Andric // %elt1(s32) = G_LOAD p0 %1 957*0fca6ea1SDimitry Andric // which could be usefully folded into: 958*0fca6ea1SDimitry Andric // %ptr(p0) = ... 959*0fca6ea1SDimitry Andric // %elt0(s32), %elt1(s32) = TGT_LOAD_PAIR %ptr 960*0fca6ea1SDimitry Andric // on some targets but we don't need to make use of that yet. 961*0fca6ea1SDimitry Andric assert(Matchers.size() == 1 && "Cannot handle multi-root matchers yet"); 962*0fca6ea1SDimitry Andric 963*0fca6ea1SDimitry Andric unsigned LabelID = Table.allocateLabelID(); 964*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_Try", +1) 965*0fca6ea1SDimitry Andric << MatchTable::Comment("On fail goto") 966*0fca6ea1SDimitry Andric << MatchTable::JumpTarget(LabelID) 967*0fca6ea1SDimitry Andric << MatchTable::Comment(("Rule ID " + Twine(RuleID) + " //").str()) 968*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 969*0fca6ea1SDimitry Andric 970*0fca6ea1SDimitry Andric if (!RequiredFeatures.empty() || HwModeIdx >= 0) { 971*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckFeatures") 972*0fca6ea1SDimitry Andric << MatchTable::NamedValue( 973*0fca6ea1SDimitry Andric 2, getNameForFeatureBitset(RequiredFeatures, HwModeIdx)) 974*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 975*0fca6ea1SDimitry Andric } 976*0fca6ea1SDimitry Andric 977*0fca6ea1SDimitry Andric if (!RequiredSimplePredicates.empty()) { 978*0fca6ea1SDimitry Andric for (const auto &Pred : RequiredSimplePredicates) { 979*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckSimplePredicate") 980*0fca6ea1SDimitry Andric << MatchTable::NamedValue(2, Pred) << MatchTable::LineBreak; 981*0fca6ea1SDimitry Andric } 982*0fca6ea1SDimitry Andric } 983*0fca6ea1SDimitry Andric 984*0fca6ea1SDimitry Andric Matchers.front()->emitPredicateOpcodes(Table, *this); 985*0fca6ea1SDimitry Andric 986*0fca6ea1SDimitry Andric // Check if it's safe to replace registers. 987*0fca6ea1SDimitry Andric for (const auto &MA : Actions) 988*0fca6ea1SDimitry Andric MA->emitAdditionalPredicates(Table, *this); 989*0fca6ea1SDimitry Andric 990*0fca6ea1SDimitry Andric // We must also check if it's safe to fold the matched instructions. 991*0fca6ea1SDimitry Andric if (InsnVariableIDs.size() >= 2) { 992*0fca6ea1SDimitry Andric 993*0fca6ea1SDimitry Andric // FIXME: Emit checks to determine it's _actually_ safe to fold and/or 994*0fca6ea1SDimitry Andric // account for unsafe cases. 995*0fca6ea1SDimitry Andric // 996*0fca6ea1SDimitry Andric // Example: 997*0fca6ea1SDimitry Andric // MI1--> %0 = ... 998*0fca6ea1SDimitry Andric // %1 = ... %0 999*0fca6ea1SDimitry Andric // MI0--> %2 = ... %0 1000*0fca6ea1SDimitry Andric // It's not safe to erase MI1. We currently handle this by not 1001*0fca6ea1SDimitry Andric // erasing %0 (even when it's dead). 1002*0fca6ea1SDimitry Andric // 1003*0fca6ea1SDimitry Andric // Example: 1004*0fca6ea1SDimitry Andric // MI1--> %0 = load volatile @a 1005*0fca6ea1SDimitry Andric // %1 = load volatile @a 1006*0fca6ea1SDimitry Andric // MI0--> %2 = ... %0 1007*0fca6ea1SDimitry Andric // It's not safe to sink %0's def past %1. We currently handle 1008*0fca6ea1SDimitry Andric // this by rejecting all loads. 1009*0fca6ea1SDimitry Andric // 1010*0fca6ea1SDimitry Andric // Example: 1011*0fca6ea1SDimitry Andric // MI1--> %0 = load @a 1012*0fca6ea1SDimitry Andric // %1 = store @a 1013*0fca6ea1SDimitry Andric // MI0--> %2 = ... %0 1014*0fca6ea1SDimitry Andric // It's not safe to sink %0's def past %1. We currently handle 1015*0fca6ea1SDimitry Andric // this by rejecting all loads. 1016*0fca6ea1SDimitry Andric // 1017*0fca6ea1SDimitry Andric // Example: 1018*0fca6ea1SDimitry Andric // G_CONDBR %cond, @BB1 1019*0fca6ea1SDimitry Andric // BB0: 1020*0fca6ea1SDimitry Andric // MI1--> %0 = load @a 1021*0fca6ea1SDimitry Andric // G_BR @BB1 1022*0fca6ea1SDimitry Andric // BB1: 1023*0fca6ea1SDimitry Andric // MI0--> %2 = ... %0 1024*0fca6ea1SDimitry Andric // It's not always safe to sink %0 across control flow. In this 1025*0fca6ea1SDimitry Andric // case it may introduce a memory fault. We currentl handle 1026*0fca6ea1SDimitry Andric // this by rejecting all loads. 1027*0fca6ea1SDimitry Andric 1028*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckIsSafeToFold") 1029*0fca6ea1SDimitry Andric << MatchTable::Comment("NumInsns") 1030*0fca6ea1SDimitry Andric << MatchTable::IntValue(1, InsnVariableIDs.size() - 1) 1031*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1032*0fca6ea1SDimitry Andric } 1033*0fca6ea1SDimitry Andric 1034*0fca6ea1SDimitry Andric for (const auto &PM : EpilogueMatchers) 1035*0fca6ea1SDimitry Andric PM->emitPredicateOpcodes(Table, *this); 1036*0fca6ea1SDimitry Andric 1037*0fca6ea1SDimitry Andric if (!CustomCXXAction.empty()) { 1038*0fca6ea1SDimitry Andric /// Handle combiners relying on custom C++ code instead of actions. 1039*0fca6ea1SDimitry Andric assert(Table.isCombiner() && "CustomCXXAction is only for combiners!"); 1040*0fca6ea1SDimitry Andric // We cannot have actions other than debug comments. 1041*0fca6ea1SDimitry Andric assert(none_of(Actions, [](auto &A) { 1042*0fca6ea1SDimitry Andric return A->getKind() != MatchAction::AK_DebugComment; 1043*0fca6ea1SDimitry Andric })); 1044*0fca6ea1SDimitry Andric for (const auto &MA : Actions) 1045*0fca6ea1SDimitry Andric MA->emitActionOpcodes(Table, *this); 1046*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_DoneWithCustomAction", -1) 1047*0fca6ea1SDimitry Andric << MatchTable::Comment("Fn") 1048*0fca6ea1SDimitry Andric << MatchTable::NamedValue(2, CustomCXXAction) 1049*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1050*0fca6ea1SDimitry Andric } else { 1051*0fca6ea1SDimitry Andric // Emit all actions except the last one, then emit coverage and emit the 1052*0fca6ea1SDimitry Andric // final action. 1053*0fca6ea1SDimitry Andric // 1054*0fca6ea1SDimitry Andric // This is because some actions, such as GIR_EraseRootFromParent_Done, also 1055*0fca6ea1SDimitry Andric // double as a GIR_Done and terminate execution of the rule. 1056*0fca6ea1SDimitry Andric if (!Actions.empty()) { 1057*0fca6ea1SDimitry Andric for (const auto &MA : drop_end(Actions)) 1058*0fca6ea1SDimitry Andric MA->emitActionOpcodes(Table, *this); 1059*0fca6ea1SDimitry Andric } 1060*0fca6ea1SDimitry Andric 1061*0fca6ea1SDimitry Andric assert((Table.isWithCoverage() ? !Table.isCombiner() : true) && 1062*0fca6ea1SDimitry Andric "Combiner tables don't support coverage!"); 1063*0fca6ea1SDimitry Andric if (Table.isWithCoverage()) 1064*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_Coverage") 1065*0fca6ea1SDimitry Andric << MatchTable::IntValue(4, RuleID) << MatchTable::LineBreak; 1066*0fca6ea1SDimitry Andric else if (!Table.isCombiner()) 1067*0fca6ea1SDimitry Andric Table << MatchTable::Comment( 1068*0fca6ea1SDimitry Andric ("GIR_Coverage, " + Twine(RuleID) + ",").str()) 1069*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1070*0fca6ea1SDimitry Andric 1071*0fca6ea1SDimitry Andric if (Actions.empty() || 1072*0fca6ea1SDimitry Andric !Actions.back()->emitActionOpcodesAndDone(Table, *this)) { 1073*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_Done", -1) << MatchTable::LineBreak; 1074*0fca6ea1SDimitry Andric } 1075*0fca6ea1SDimitry Andric } 1076*0fca6ea1SDimitry Andric 1077*0fca6ea1SDimitry Andric Table << MatchTable::Label(LabelID); 1078*0fca6ea1SDimitry Andric ++NumPatternEmitted; 1079*0fca6ea1SDimitry Andric } 1080*0fca6ea1SDimitry Andric 1081*0fca6ea1SDimitry Andric bool RuleMatcher::isHigherPriorityThan(const RuleMatcher &B) const { 1082*0fca6ea1SDimitry Andric // Rules involving more match roots have higher priority. 1083*0fca6ea1SDimitry Andric if (Matchers.size() > B.Matchers.size()) 1084*0fca6ea1SDimitry Andric return true; 1085*0fca6ea1SDimitry Andric if (Matchers.size() < B.Matchers.size()) 1086*0fca6ea1SDimitry Andric return false; 1087*0fca6ea1SDimitry Andric 1088*0fca6ea1SDimitry Andric for (auto Matcher : zip(Matchers, B.Matchers)) { 1089*0fca6ea1SDimitry Andric if (std::get<0>(Matcher)->isHigherPriorityThan(*std::get<1>(Matcher))) 1090*0fca6ea1SDimitry Andric return true; 1091*0fca6ea1SDimitry Andric if (std::get<1>(Matcher)->isHigherPriorityThan(*std::get<0>(Matcher))) 1092*0fca6ea1SDimitry Andric return false; 1093*0fca6ea1SDimitry Andric } 1094*0fca6ea1SDimitry Andric 1095*0fca6ea1SDimitry Andric return false; 1096*0fca6ea1SDimitry Andric } 1097*0fca6ea1SDimitry Andric 1098*0fca6ea1SDimitry Andric unsigned RuleMatcher::countRendererFns() const { 1099*0fca6ea1SDimitry Andric return std::accumulate( 1100*0fca6ea1SDimitry Andric Matchers.begin(), Matchers.end(), 0, 1101*0fca6ea1SDimitry Andric [](unsigned A, const std::unique_ptr<InstructionMatcher> &Matcher) { 1102*0fca6ea1SDimitry Andric return A + Matcher->countRendererFns(); 1103*0fca6ea1SDimitry Andric }); 1104*0fca6ea1SDimitry Andric } 1105*0fca6ea1SDimitry Andric 1106*0fca6ea1SDimitry Andric //===- PredicateMatcher ---------------------------------------------------===// 1107*0fca6ea1SDimitry Andric 1108*0fca6ea1SDimitry Andric PredicateMatcher::~PredicateMatcher() {} 1109*0fca6ea1SDimitry Andric 1110*0fca6ea1SDimitry Andric //===- OperandPredicateMatcher --------------------------------------------===// 1111*0fca6ea1SDimitry Andric 1112*0fca6ea1SDimitry Andric OperandPredicateMatcher::~OperandPredicateMatcher() {} 1113*0fca6ea1SDimitry Andric 1114*0fca6ea1SDimitry Andric bool OperandPredicateMatcher::isHigherPriorityThan( 1115*0fca6ea1SDimitry Andric const OperandPredicateMatcher &B) const { 1116*0fca6ea1SDimitry Andric // Generally speaking, an instruction is more important than an Int or a 1117*0fca6ea1SDimitry Andric // LiteralInt because it can cover more nodes but there's an exception to 1118*0fca6ea1SDimitry Andric // this. G_CONSTANT's are less important than either of those two because they 1119*0fca6ea1SDimitry Andric // are more permissive. 1120*0fca6ea1SDimitry Andric 1121*0fca6ea1SDimitry Andric const auto *AOM = dyn_cast<InstructionOperandMatcher>(this); 1122*0fca6ea1SDimitry Andric const auto *BOM = dyn_cast<InstructionOperandMatcher>(&B); 1123*0fca6ea1SDimitry Andric bool AIsConstantInsn = AOM && AOM->getInsnMatcher().isConstantInstruction(); 1124*0fca6ea1SDimitry Andric bool BIsConstantInsn = BOM && BOM->getInsnMatcher().isConstantInstruction(); 1125*0fca6ea1SDimitry Andric 1126*0fca6ea1SDimitry Andric // The relative priorities between a G_CONSTANT and any other instruction 1127*0fca6ea1SDimitry Andric // don't actually matter but this code is needed to ensure a strict weak 1128*0fca6ea1SDimitry Andric // ordering. This is particularly important on Windows where the rules will 1129*0fca6ea1SDimitry Andric // be incorrectly sorted without it. 1130*0fca6ea1SDimitry Andric if (AOM && BOM) 1131*0fca6ea1SDimitry Andric return !AIsConstantInsn && BIsConstantInsn; 1132*0fca6ea1SDimitry Andric 1133*0fca6ea1SDimitry Andric if (AIsConstantInsn && (B.Kind == OPM_Int || B.Kind == OPM_LiteralInt)) 1134*0fca6ea1SDimitry Andric return false; 1135*0fca6ea1SDimitry Andric if (BIsConstantInsn && (Kind == OPM_Int || Kind == OPM_LiteralInt)) 1136*0fca6ea1SDimitry Andric return true; 1137*0fca6ea1SDimitry Andric 1138*0fca6ea1SDimitry Andric return Kind < B.Kind; 1139*0fca6ea1SDimitry Andric } 1140*0fca6ea1SDimitry Andric 1141*0fca6ea1SDimitry Andric //===- SameOperandMatcher -------------------------------------------------===// 1142*0fca6ea1SDimitry Andric 1143*0fca6ea1SDimitry Andric void SameOperandMatcher::emitPredicateOpcodes(MatchTable &Table, 1144*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1145*0fca6ea1SDimitry Andric const OperandMatcher &OtherOM = Rule.getOperandMatcher(MatchingName); 1146*0fca6ea1SDimitry Andric unsigned OtherInsnVarID = Rule.getInsnVarID(OtherOM.getInstructionMatcher()); 1147*0fca6ea1SDimitry Andric assert(OtherInsnVarID == OtherOM.getInstructionMatcher().getInsnVarID()); 1148*0fca6ea1SDimitry Andric const bool IgnoreCopies = Flags & GISF_IgnoreCopies; 1149*0fca6ea1SDimitry Andric Table << MatchTable::Opcode(IgnoreCopies 1150*0fca6ea1SDimitry Andric ? "GIM_CheckIsSameOperandIgnoreCopies" 1151*0fca6ea1SDimitry Andric : "GIM_CheckIsSameOperand") 1152*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1153*0fca6ea1SDimitry Andric << MatchTable::Comment("OpIdx") << MatchTable::ULEB128Value(OpIdx) 1154*0fca6ea1SDimitry Andric << MatchTable::Comment("OtherMI") 1155*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OtherInsnVarID) 1156*0fca6ea1SDimitry Andric << MatchTable::Comment("OtherOpIdx") 1157*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OtherOM.getOpIdx()) 1158*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1159*0fca6ea1SDimitry Andric } 1160*0fca6ea1SDimitry Andric 1161*0fca6ea1SDimitry Andric //===- LLTOperandMatcher --------------------------------------------------===// 1162*0fca6ea1SDimitry Andric 1163*0fca6ea1SDimitry Andric std::map<LLTCodeGen, unsigned> LLTOperandMatcher::TypeIDValues; 1164*0fca6ea1SDimitry Andric 1165*0fca6ea1SDimitry Andric MatchTableRecord LLTOperandMatcher::getValue() const { 1166*0fca6ea1SDimitry Andric const auto VI = TypeIDValues.find(Ty); 1167*0fca6ea1SDimitry Andric if (VI == TypeIDValues.end()) 1168*0fca6ea1SDimitry Andric return MatchTable::NamedValue(1, getTy().getCxxEnumValue()); 1169*0fca6ea1SDimitry Andric return MatchTable::NamedValue(1, getTy().getCxxEnumValue(), VI->second); 1170*0fca6ea1SDimitry Andric } 1171*0fca6ea1SDimitry Andric 1172*0fca6ea1SDimitry Andric bool LLTOperandMatcher::hasValue() const { 1173*0fca6ea1SDimitry Andric if (TypeIDValues.size() != KnownTypes.size()) 1174*0fca6ea1SDimitry Andric initTypeIDValuesMap(); 1175*0fca6ea1SDimitry Andric return TypeIDValues.count(Ty); 1176*0fca6ea1SDimitry Andric } 1177*0fca6ea1SDimitry Andric 1178*0fca6ea1SDimitry Andric void LLTOperandMatcher::emitPredicateOpcodes(MatchTable &Table, 1179*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1180*0fca6ea1SDimitry Andric if (InsnVarID == 0) { 1181*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_RootCheckType"); 1182*0fca6ea1SDimitry Andric } else { 1183*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckType") << MatchTable::Comment("MI") 1184*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(InsnVarID); 1185*0fca6ea1SDimitry Andric } 1186*0fca6ea1SDimitry Andric Table << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx) 1187*0fca6ea1SDimitry Andric << MatchTable::Comment("Type") << getValue() << MatchTable::LineBreak; 1188*0fca6ea1SDimitry Andric } 1189*0fca6ea1SDimitry Andric 1190*0fca6ea1SDimitry Andric //===- PointerToAnyOperandMatcher -----------------------------------------===// 1191*0fca6ea1SDimitry Andric 1192*0fca6ea1SDimitry Andric void PointerToAnyOperandMatcher::emitPredicateOpcodes(MatchTable &Table, 1193*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1194*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckPointerToAny") 1195*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1196*0fca6ea1SDimitry Andric << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx) 1197*0fca6ea1SDimitry Andric << MatchTable::Comment("SizeInBits") 1198*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(SizeInBits) << MatchTable::LineBreak; 1199*0fca6ea1SDimitry Andric } 1200*0fca6ea1SDimitry Andric 1201*0fca6ea1SDimitry Andric //===- RecordNamedOperandMatcher ------------------------------------------===// 1202*0fca6ea1SDimitry Andric 1203*0fca6ea1SDimitry Andric void RecordNamedOperandMatcher::emitPredicateOpcodes(MatchTable &Table, 1204*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1205*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_RecordNamedOperand") 1206*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1207*0fca6ea1SDimitry Andric << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx) 1208*0fca6ea1SDimitry Andric << MatchTable::Comment("StoreIdx") << MatchTable::ULEB128Value(StoreIdx) 1209*0fca6ea1SDimitry Andric << MatchTable::Comment("Name : " + Name) << MatchTable::LineBreak; 1210*0fca6ea1SDimitry Andric } 1211*0fca6ea1SDimitry Andric 1212*0fca6ea1SDimitry Andric //===- RecordRegisterType ------------------------------------------===// 1213*0fca6ea1SDimitry Andric 1214*0fca6ea1SDimitry Andric void RecordRegisterType::emitPredicateOpcodes(MatchTable &Table, 1215*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1216*0fca6ea1SDimitry Andric assert(Idx < 0 && "Temp types always have negative indexes!"); 1217*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_RecordRegType") << MatchTable::Comment("MI") 1218*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(InsnVarID) << MatchTable::Comment("Op") 1219*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OpIdx) << MatchTable::Comment("TempTypeIdx") 1220*0fca6ea1SDimitry Andric << MatchTable::IntValue(1, Idx) << MatchTable::LineBreak; 1221*0fca6ea1SDimitry Andric } 1222*0fca6ea1SDimitry Andric 1223*0fca6ea1SDimitry Andric //===- ComplexPatternOperandMatcher ---------------------------------------===// 1224*0fca6ea1SDimitry Andric 1225*0fca6ea1SDimitry Andric void ComplexPatternOperandMatcher::emitPredicateOpcodes( 1226*0fca6ea1SDimitry Andric MatchTable &Table, RuleMatcher &Rule) const { 1227*0fca6ea1SDimitry Andric unsigned ID = getAllocatedTemporariesBaseID(); 1228*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckComplexPattern") 1229*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1230*0fca6ea1SDimitry Andric << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx) 1231*0fca6ea1SDimitry Andric << MatchTable::Comment("Renderer") << MatchTable::IntValue(2, ID) 1232*0fca6ea1SDimitry Andric << MatchTable::NamedValue(2, ("GICP_" + TheDef.getName()).str()) 1233*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1234*0fca6ea1SDimitry Andric } 1235*0fca6ea1SDimitry Andric 1236*0fca6ea1SDimitry Andric unsigned ComplexPatternOperandMatcher::getAllocatedTemporariesBaseID() const { 1237*0fca6ea1SDimitry Andric return Operand.getAllocatedTemporariesBaseID(); 1238*0fca6ea1SDimitry Andric } 1239*0fca6ea1SDimitry Andric 1240*0fca6ea1SDimitry Andric //===- RegisterBankOperandMatcher -----------------------------------------===// 1241*0fca6ea1SDimitry Andric 1242*0fca6ea1SDimitry Andric bool RegisterBankOperandMatcher::isIdentical(const PredicateMatcher &B) const { 1243*0fca6ea1SDimitry Andric return OperandPredicateMatcher::isIdentical(B) && 1244*0fca6ea1SDimitry Andric RC.getDef() == cast<RegisterBankOperandMatcher>(&B)->RC.getDef(); 1245*0fca6ea1SDimitry Andric } 1246*0fca6ea1SDimitry Andric 1247*0fca6ea1SDimitry Andric void RegisterBankOperandMatcher::emitPredicateOpcodes(MatchTable &Table, 1248*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1249*0fca6ea1SDimitry Andric if (InsnVarID == 0) { 1250*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_RootCheckRegBankForClass"); 1251*0fca6ea1SDimitry Andric } else { 1252*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckRegBankForClass") 1253*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID); 1254*0fca6ea1SDimitry Andric } 1255*0fca6ea1SDimitry Andric 1256*0fca6ea1SDimitry Andric Table << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx) 1257*0fca6ea1SDimitry Andric << MatchTable::Comment("RC") 1258*0fca6ea1SDimitry Andric << MatchTable::NamedValue(2, RC.getQualifiedIdName()) 1259*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1260*0fca6ea1SDimitry Andric } 1261*0fca6ea1SDimitry Andric 1262*0fca6ea1SDimitry Andric //===- MBBOperandMatcher --------------------------------------------------===// 1263*0fca6ea1SDimitry Andric 1264*0fca6ea1SDimitry Andric void MBBOperandMatcher::emitPredicateOpcodes(MatchTable &Table, 1265*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1266*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckIsMBB") << MatchTable::Comment("MI") 1267*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(InsnVarID) << MatchTable::Comment("Op") 1268*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OpIdx) << MatchTable::LineBreak; 1269*0fca6ea1SDimitry Andric } 1270*0fca6ea1SDimitry Andric 1271*0fca6ea1SDimitry Andric //===- ImmOperandMatcher --------------------------------------------------===// 1272*0fca6ea1SDimitry Andric 1273*0fca6ea1SDimitry Andric void ImmOperandMatcher::emitPredicateOpcodes(MatchTable &Table, 1274*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1275*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckIsImm") << MatchTable::Comment("MI") 1276*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(InsnVarID) << MatchTable::Comment("Op") 1277*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OpIdx) << MatchTable::LineBreak; 1278*0fca6ea1SDimitry Andric } 1279*0fca6ea1SDimitry Andric 1280*0fca6ea1SDimitry Andric //===- ConstantIntOperandMatcher ------------------------------------------===// 1281*0fca6ea1SDimitry Andric 1282*0fca6ea1SDimitry Andric void ConstantIntOperandMatcher::emitPredicateOpcodes(MatchTable &Table, 1283*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1284*0fca6ea1SDimitry Andric const bool IsInt8 = isInt<8>(Value); 1285*0fca6ea1SDimitry Andric Table << MatchTable::Opcode(IsInt8 ? "GIM_CheckConstantInt8" 1286*0fca6ea1SDimitry Andric : "GIM_CheckConstantInt") 1287*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1288*0fca6ea1SDimitry Andric << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx) 1289*0fca6ea1SDimitry Andric << MatchTable::IntValue(IsInt8 ? 1 : 8, Value) << MatchTable::LineBreak; 1290*0fca6ea1SDimitry Andric } 1291*0fca6ea1SDimitry Andric 1292*0fca6ea1SDimitry Andric //===- LiteralIntOperandMatcher -------------------------------------------===// 1293*0fca6ea1SDimitry Andric 1294*0fca6ea1SDimitry Andric void LiteralIntOperandMatcher::emitPredicateOpcodes(MatchTable &Table, 1295*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1296*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckLiteralInt") 1297*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1298*0fca6ea1SDimitry Andric << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx) 1299*0fca6ea1SDimitry Andric << MatchTable::IntValue(8, Value) << MatchTable::LineBreak; 1300*0fca6ea1SDimitry Andric } 1301*0fca6ea1SDimitry Andric 1302*0fca6ea1SDimitry Andric //===- CmpPredicateOperandMatcher -----------------------------------------===// 1303*0fca6ea1SDimitry Andric 1304*0fca6ea1SDimitry Andric void CmpPredicateOperandMatcher::emitPredicateOpcodes(MatchTable &Table, 1305*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1306*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckCmpPredicate") 1307*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1308*0fca6ea1SDimitry Andric << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx) 1309*0fca6ea1SDimitry Andric << MatchTable::Comment("Predicate") 1310*0fca6ea1SDimitry Andric << MatchTable::NamedValue(2, "CmpInst", PredName) 1311*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1312*0fca6ea1SDimitry Andric } 1313*0fca6ea1SDimitry Andric 1314*0fca6ea1SDimitry Andric //===- IntrinsicIDOperandMatcher ------------------------------------------===// 1315*0fca6ea1SDimitry Andric 1316*0fca6ea1SDimitry Andric void IntrinsicIDOperandMatcher::emitPredicateOpcodes(MatchTable &Table, 1317*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1318*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckIntrinsicID") 1319*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1320*0fca6ea1SDimitry Andric << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx) 1321*0fca6ea1SDimitry Andric << MatchTable::NamedValue(2, "Intrinsic::" + II->EnumName) 1322*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1323*0fca6ea1SDimitry Andric } 1324*0fca6ea1SDimitry Andric 1325*0fca6ea1SDimitry Andric //===- OperandImmPredicateMatcher -----------------------------------------===// 1326*0fca6ea1SDimitry Andric 1327*0fca6ea1SDimitry Andric void OperandImmPredicateMatcher::emitPredicateOpcodes(MatchTable &Table, 1328*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1329*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckImmOperandPredicate") 1330*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1331*0fca6ea1SDimitry Andric << MatchTable::Comment("MO") << MatchTable::ULEB128Value(OpIdx) 1332*0fca6ea1SDimitry Andric << MatchTable::Comment("Predicate") 1333*0fca6ea1SDimitry Andric << MatchTable::NamedValue(2, getEnumNameForPredicate(Predicate)) 1334*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1335*0fca6ea1SDimitry Andric } 1336*0fca6ea1SDimitry Andric 1337*0fca6ea1SDimitry Andric //===- OperandMatcher -----------------------------------------------------===// 1338*0fca6ea1SDimitry Andric 1339*0fca6ea1SDimitry Andric std::string OperandMatcher::getOperandExpr(unsigned InsnVarID) const { 1340*0fca6ea1SDimitry Andric return "State.MIs[" + llvm::to_string(InsnVarID) + "]->getOperand(" + 1341*0fca6ea1SDimitry Andric llvm::to_string(OpIdx) + ")"; 1342*0fca6ea1SDimitry Andric } 1343*0fca6ea1SDimitry Andric 1344*0fca6ea1SDimitry Andric unsigned OperandMatcher::getInsnVarID() const { return Insn.getInsnVarID(); } 1345*0fca6ea1SDimitry Andric 1346*0fca6ea1SDimitry Andric TempTypeIdx OperandMatcher::getTempTypeIdx(RuleMatcher &Rule) { 1347*0fca6ea1SDimitry Andric if (TTIdx >= 0) { 1348*0fca6ea1SDimitry Andric // Temp type index not assigned yet, so assign one and add the necessary 1349*0fca6ea1SDimitry Andric // predicate. 1350*0fca6ea1SDimitry Andric TTIdx = Rule.getNextTempTypeIdx(); 1351*0fca6ea1SDimitry Andric assert(TTIdx < 0); 1352*0fca6ea1SDimitry Andric addPredicate<RecordRegisterType>(TTIdx); 1353*0fca6ea1SDimitry Andric return TTIdx; 1354*0fca6ea1SDimitry Andric } 1355*0fca6ea1SDimitry Andric return TTIdx; 1356*0fca6ea1SDimitry Andric } 1357*0fca6ea1SDimitry Andric 1358*0fca6ea1SDimitry Andric void OperandMatcher::emitPredicateOpcodes(MatchTable &Table, 1359*0fca6ea1SDimitry Andric RuleMatcher &Rule) { 1360*0fca6ea1SDimitry Andric if (!Optimized) { 1361*0fca6ea1SDimitry Andric std::string Comment; 1362*0fca6ea1SDimitry Andric raw_string_ostream CommentOS(Comment); 1363*0fca6ea1SDimitry Andric CommentOS << "MIs[" << getInsnVarID() << "] "; 1364*0fca6ea1SDimitry Andric if (SymbolicName.empty()) 1365*0fca6ea1SDimitry Andric CommentOS << "Operand " << OpIdx; 1366*0fca6ea1SDimitry Andric else 1367*0fca6ea1SDimitry Andric CommentOS << SymbolicName; 1368*0fca6ea1SDimitry Andric Table << MatchTable::Comment(Comment) << MatchTable::LineBreak; 1369*0fca6ea1SDimitry Andric } 1370*0fca6ea1SDimitry Andric 1371*0fca6ea1SDimitry Andric emitPredicateListOpcodes(Table, Rule); 1372*0fca6ea1SDimitry Andric } 1373*0fca6ea1SDimitry Andric 1374*0fca6ea1SDimitry Andric bool OperandMatcher::isHigherPriorityThan(OperandMatcher &B) { 1375*0fca6ea1SDimitry Andric // Operand matchers involving more predicates have higher priority. 1376*0fca6ea1SDimitry Andric if (predicates_size() > B.predicates_size()) 1377*0fca6ea1SDimitry Andric return true; 1378*0fca6ea1SDimitry Andric if (predicates_size() < B.predicates_size()) 1379*0fca6ea1SDimitry Andric return false; 1380*0fca6ea1SDimitry Andric 1381*0fca6ea1SDimitry Andric // This assumes that predicates are added in a consistent order. 1382*0fca6ea1SDimitry Andric for (auto &&Predicate : zip(predicates(), B.predicates())) { 1383*0fca6ea1SDimitry Andric if (std::get<0>(Predicate)->isHigherPriorityThan(*std::get<1>(Predicate))) 1384*0fca6ea1SDimitry Andric return true; 1385*0fca6ea1SDimitry Andric if (std::get<1>(Predicate)->isHigherPriorityThan(*std::get<0>(Predicate))) 1386*0fca6ea1SDimitry Andric return false; 1387*0fca6ea1SDimitry Andric } 1388*0fca6ea1SDimitry Andric 1389*0fca6ea1SDimitry Andric return false; 1390*0fca6ea1SDimitry Andric } 1391*0fca6ea1SDimitry Andric 1392*0fca6ea1SDimitry Andric unsigned OperandMatcher::countRendererFns() { 1393*0fca6ea1SDimitry Andric return std::accumulate( 1394*0fca6ea1SDimitry Andric predicates().begin(), predicates().end(), 0, 1395*0fca6ea1SDimitry Andric [](unsigned A, 1396*0fca6ea1SDimitry Andric const std::unique_ptr<OperandPredicateMatcher> &Predicate) { 1397*0fca6ea1SDimitry Andric return A + Predicate->countRendererFns(); 1398*0fca6ea1SDimitry Andric }); 1399*0fca6ea1SDimitry Andric } 1400*0fca6ea1SDimitry Andric 1401*0fca6ea1SDimitry Andric Error OperandMatcher::addTypeCheckPredicate(const TypeSetByHwMode &VTy, 1402*0fca6ea1SDimitry Andric bool OperandIsAPointer) { 1403*0fca6ea1SDimitry Andric if (!VTy.isMachineValueType()) 1404*0fca6ea1SDimitry Andric return failUnsupported("unsupported typeset"); 1405*0fca6ea1SDimitry Andric 1406*0fca6ea1SDimitry Andric if (VTy.getMachineValueType() == MVT::iPTR && OperandIsAPointer) { 1407*0fca6ea1SDimitry Andric addPredicate<PointerToAnyOperandMatcher>(0); 1408*0fca6ea1SDimitry Andric return Error::success(); 1409*0fca6ea1SDimitry Andric } 1410*0fca6ea1SDimitry Andric 1411*0fca6ea1SDimitry Andric auto OpTyOrNone = MVTToLLT(VTy.getMachineValueType().SimpleTy); 1412*0fca6ea1SDimitry Andric if (!OpTyOrNone) 1413*0fca6ea1SDimitry Andric return failUnsupported("unsupported type"); 1414*0fca6ea1SDimitry Andric 1415*0fca6ea1SDimitry Andric if (OperandIsAPointer) 1416*0fca6ea1SDimitry Andric addPredicate<PointerToAnyOperandMatcher>(OpTyOrNone->get().getSizeInBits()); 1417*0fca6ea1SDimitry Andric else if (VTy.isPointer()) 1418*0fca6ea1SDimitry Andric addPredicate<LLTOperandMatcher>( 1419*0fca6ea1SDimitry Andric LLT::pointer(VTy.getPtrAddrSpace(), OpTyOrNone->get().getSizeInBits())); 1420*0fca6ea1SDimitry Andric else 1421*0fca6ea1SDimitry Andric addPredicate<LLTOperandMatcher>(*OpTyOrNone); 1422*0fca6ea1SDimitry Andric return Error::success(); 1423*0fca6ea1SDimitry Andric } 1424*0fca6ea1SDimitry Andric 1425*0fca6ea1SDimitry Andric //===- InstructionOpcodeMatcher -------------------------------------------===// 1426*0fca6ea1SDimitry Andric 1427*0fca6ea1SDimitry Andric DenseMap<const CodeGenInstruction *, unsigned> 1428*0fca6ea1SDimitry Andric InstructionOpcodeMatcher::OpcodeValues; 1429*0fca6ea1SDimitry Andric 1430*0fca6ea1SDimitry Andric MatchTableRecord 1431*0fca6ea1SDimitry Andric InstructionOpcodeMatcher::getInstValue(const CodeGenInstruction *I) const { 1432*0fca6ea1SDimitry Andric const auto VI = OpcodeValues.find(I); 1433*0fca6ea1SDimitry Andric if (VI != OpcodeValues.end()) 1434*0fca6ea1SDimitry Andric return MatchTable::NamedValue(2, I->Namespace, I->TheDef->getName(), 1435*0fca6ea1SDimitry Andric VI->second); 1436*0fca6ea1SDimitry Andric return MatchTable::NamedValue(2, I->Namespace, I->TheDef->getName()); 1437*0fca6ea1SDimitry Andric } 1438*0fca6ea1SDimitry Andric 1439*0fca6ea1SDimitry Andric void InstructionOpcodeMatcher::initOpcodeValuesMap( 1440*0fca6ea1SDimitry Andric const CodeGenTarget &Target) { 1441*0fca6ea1SDimitry Andric OpcodeValues.clear(); 1442*0fca6ea1SDimitry Andric 1443*0fca6ea1SDimitry Andric for (const CodeGenInstruction *I : Target.getInstructionsByEnumValue()) 1444*0fca6ea1SDimitry Andric OpcodeValues[I] = Target.getInstrIntValue(I->TheDef); 1445*0fca6ea1SDimitry Andric } 1446*0fca6ea1SDimitry Andric 1447*0fca6ea1SDimitry Andric MatchTableRecord InstructionOpcodeMatcher::getValue() const { 1448*0fca6ea1SDimitry Andric assert(Insts.size() == 1); 1449*0fca6ea1SDimitry Andric 1450*0fca6ea1SDimitry Andric const CodeGenInstruction *I = Insts[0]; 1451*0fca6ea1SDimitry Andric const auto VI = OpcodeValues.find(I); 1452*0fca6ea1SDimitry Andric if (VI != OpcodeValues.end()) 1453*0fca6ea1SDimitry Andric return MatchTable::NamedValue(2, I->Namespace, I->TheDef->getName(), 1454*0fca6ea1SDimitry Andric VI->second); 1455*0fca6ea1SDimitry Andric return MatchTable::NamedValue(2, I->Namespace, I->TheDef->getName()); 1456*0fca6ea1SDimitry Andric } 1457*0fca6ea1SDimitry Andric 1458*0fca6ea1SDimitry Andric void InstructionOpcodeMatcher::emitPredicateOpcodes(MatchTable &Table, 1459*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1460*0fca6ea1SDimitry Andric StringRef CheckType = 1461*0fca6ea1SDimitry Andric Insts.size() == 1 ? "GIM_CheckOpcode" : "GIM_CheckOpcodeIsEither"; 1462*0fca6ea1SDimitry Andric Table << MatchTable::Opcode(CheckType) << MatchTable::Comment("MI") 1463*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(InsnVarID); 1464*0fca6ea1SDimitry Andric 1465*0fca6ea1SDimitry Andric for (const CodeGenInstruction *I : Insts) 1466*0fca6ea1SDimitry Andric Table << getInstValue(I); 1467*0fca6ea1SDimitry Andric Table << MatchTable::LineBreak; 1468*0fca6ea1SDimitry Andric } 1469*0fca6ea1SDimitry Andric 1470*0fca6ea1SDimitry Andric bool InstructionOpcodeMatcher::isHigherPriorityThan( 1471*0fca6ea1SDimitry Andric const InstructionPredicateMatcher &B) const { 1472*0fca6ea1SDimitry Andric if (InstructionPredicateMatcher::isHigherPriorityThan(B)) 1473*0fca6ea1SDimitry Andric return true; 1474*0fca6ea1SDimitry Andric if (B.InstructionPredicateMatcher::isHigherPriorityThan(*this)) 1475*0fca6ea1SDimitry Andric return false; 1476*0fca6ea1SDimitry Andric 1477*0fca6ea1SDimitry Andric // Prioritize opcodes for cosmetic reasons in the generated source. Although 1478*0fca6ea1SDimitry Andric // this is cosmetic at the moment, we may want to drive a similar ordering 1479*0fca6ea1SDimitry Andric // using instruction frequency information to improve compile time. 1480*0fca6ea1SDimitry Andric if (const InstructionOpcodeMatcher *BO = 1481*0fca6ea1SDimitry Andric dyn_cast<InstructionOpcodeMatcher>(&B)) 1482*0fca6ea1SDimitry Andric return Insts[0]->TheDef->getName() < BO->Insts[0]->TheDef->getName(); 1483*0fca6ea1SDimitry Andric 1484*0fca6ea1SDimitry Andric return false; 1485*0fca6ea1SDimitry Andric } 1486*0fca6ea1SDimitry Andric 1487*0fca6ea1SDimitry Andric bool InstructionOpcodeMatcher::isConstantInstruction() const { 1488*0fca6ea1SDimitry Andric return Insts.size() == 1 && Insts[0]->TheDef->getName() == "G_CONSTANT"; 1489*0fca6ea1SDimitry Andric } 1490*0fca6ea1SDimitry Andric 1491*0fca6ea1SDimitry Andric StringRef InstructionOpcodeMatcher::getOpcode() const { 1492*0fca6ea1SDimitry Andric return Insts[0]->TheDef->getName(); 1493*0fca6ea1SDimitry Andric } 1494*0fca6ea1SDimitry Andric 1495*0fca6ea1SDimitry Andric bool InstructionOpcodeMatcher::isVariadicNumOperands() const { 1496*0fca6ea1SDimitry Andric // If one is variadic, they all should be. 1497*0fca6ea1SDimitry Andric return Insts[0]->Operands.isVariadic; 1498*0fca6ea1SDimitry Andric } 1499*0fca6ea1SDimitry Andric 1500*0fca6ea1SDimitry Andric StringRef InstructionOpcodeMatcher::getOperandType(unsigned OpIdx) const { 1501*0fca6ea1SDimitry Andric // Types expected to be uniform for all alternatives. 1502*0fca6ea1SDimitry Andric return Insts[0]->Operands[OpIdx].OperandType; 1503*0fca6ea1SDimitry Andric } 1504*0fca6ea1SDimitry Andric 1505*0fca6ea1SDimitry Andric //===- InstructionNumOperandsMatcher --------------------------------------===// 1506*0fca6ea1SDimitry Andric 1507*0fca6ea1SDimitry Andric void InstructionNumOperandsMatcher::emitPredicateOpcodes( 1508*0fca6ea1SDimitry Andric MatchTable &Table, RuleMatcher &Rule) const { 1509*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckNumOperands") 1510*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1511*0fca6ea1SDimitry Andric << MatchTable::Comment("Expected") 1512*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(NumOperands) << MatchTable::LineBreak; 1513*0fca6ea1SDimitry Andric } 1514*0fca6ea1SDimitry Andric 1515*0fca6ea1SDimitry Andric //===- InstructionImmPredicateMatcher -------------------------------------===// 1516*0fca6ea1SDimitry Andric 1517*0fca6ea1SDimitry Andric bool InstructionImmPredicateMatcher::isIdentical( 1518*0fca6ea1SDimitry Andric const PredicateMatcher &B) const { 1519*0fca6ea1SDimitry Andric return InstructionPredicateMatcher::isIdentical(B) && 1520*0fca6ea1SDimitry Andric Predicate.getOrigPatFragRecord() == 1521*0fca6ea1SDimitry Andric cast<InstructionImmPredicateMatcher>(&B) 1522*0fca6ea1SDimitry Andric ->Predicate.getOrigPatFragRecord(); 1523*0fca6ea1SDimitry Andric } 1524*0fca6ea1SDimitry Andric 1525*0fca6ea1SDimitry Andric void InstructionImmPredicateMatcher::emitPredicateOpcodes( 1526*0fca6ea1SDimitry Andric MatchTable &Table, RuleMatcher &Rule) const { 1527*0fca6ea1SDimitry Andric Table << MatchTable::Opcode(getMatchOpcodeForImmPredicate(Predicate)) 1528*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1529*0fca6ea1SDimitry Andric << MatchTable::Comment("Predicate") 1530*0fca6ea1SDimitry Andric << MatchTable::NamedValue(2, getEnumNameForPredicate(Predicate)) 1531*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1532*0fca6ea1SDimitry Andric } 1533*0fca6ea1SDimitry Andric 1534*0fca6ea1SDimitry Andric //===- AtomicOrderingMMOPredicateMatcher ----------------------------------===// 1535*0fca6ea1SDimitry Andric 1536*0fca6ea1SDimitry Andric bool AtomicOrderingMMOPredicateMatcher::isIdentical( 1537*0fca6ea1SDimitry Andric const PredicateMatcher &B) const { 1538*0fca6ea1SDimitry Andric if (!InstructionPredicateMatcher::isIdentical(B)) 1539*0fca6ea1SDimitry Andric return false; 1540*0fca6ea1SDimitry Andric const auto &R = *cast<AtomicOrderingMMOPredicateMatcher>(&B); 1541*0fca6ea1SDimitry Andric return Order == R.Order && Comparator == R.Comparator; 1542*0fca6ea1SDimitry Andric } 1543*0fca6ea1SDimitry Andric 1544*0fca6ea1SDimitry Andric void AtomicOrderingMMOPredicateMatcher::emitPredicateOpcodes( 1545*0fca6ea1SDimitry Andric MatchTable &Table, RuleMatcher &Rule) const { 1546*0fca6ea1SDimitry Andric StringRef Opcode = "GIM_CheckAtomicOrdering"; 1547*0fca6ea1SDimitry Andric 1548*0fca6ea1SDimitry Andric if (Comparator == AO_OrStronger) 1549*0fca6ea1SDimitry Andric Opcode = "GIM_CheckAtomicOrderingOrStrongerThan"; 1550*0fca6ea1SDimitry Andric if (Comparator == AO_WeakerThan) 1551*0fca6ea1SDimitry Andric Opcode = "GIM_CheckAtomicOrderingWeakerThan"; 1552*0fca6ea1SDimitry Andric 1553*0fca6ea1SDimitry Andric Table << MatchTable::Opcode(Opcode) << MatchTable::Comment("MI") 1554*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(InsnVarID) << MatchTable::Comment("Order") 1555*0fca6ea1SDimitry Andric << MatchTable::NamedValue(1, 1556*0fca6ea1SDimitry Andric ("(uint8_t)AtomicOrdering::" + Order).str()) 1557*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1558*0fca6ea1SDimitry Andric } 1559*0fca6ea1SDimitry Andric 1560*0fca6ea1SDimitry Andric //===- MemorySizePredicateMatcher -----------------------------------------===// 1561*0fca6ea1SDimitry Andric 1562*0fca6ea1SDimitry Andric void MemorySizePredicateMatcher::emitPredicateOpcodes(MatchTable &Table, 1563*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1564*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckMemorySizeEqualTo") 1565*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1566*0fca6ea1SDimitry Andric << MatchTable::Comment("MMO") << MatchTable::ULEB128Value(MMOIdx) 1567*0fca6ea1SDimitry Andric << MatchTable::Comment("Size") << MatchTable::IntValue(4, Size) 1568*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1569*0fca6ea1SDimitry Andric } 1570*0fca6ea1SDimitry Andric 1571*0fca6ea1SDimitry Andric //===- MemoryAddressSpacePredicateMatcher ---------------------------------===// 1572*0fca6ea1SDimitry Andric 1573*0fca6ea1SDimitry Andric bool MemoryAddressSpacePredicateMatcher::isIdentical( 1574*0fca6ea1SDimitry Andric const PredicateMatcher &B) const { 1575*0fca6ea1SDimitry Andric if (!InstructionPredicateMatcher::isIdentical(B)) 1576*0fca6ea1SDimitry Andric return false; 1577*0fca6ea1SDimitry Andric auto *Other = cast<MemoryAddressSpacePredicateMatcher>(&B); 1578*0fca6ea1SDimitry Andric return MMOIdx == Other->MMOIdx && AddrSpaces == Other->AddrSpaces; 1579*0fca6ea1SDimitry Andric } 1580*0fca6ea1SDimitry Andric 1581*0fca6ea1SDimitry Andric void MemoryAddressSpacePredicateMatcher::emitPredicateOpcodes( 1582*0fca6ea1SDimitry Andric MatchTable &Table, RuleMatcher &Rule) const { 1583*0fca6ea1SDimitry Andric assert(AddrSpaces.size() < 256); 1584*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckMemoryAddressSpace") 1585*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1586*0fca6ea1SDimitry Andric << MatchTable::Comment("MMO") 1587*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(MMOIdx) 1588*0fca6ea1SDimitry Andric // Encode number of address spaces to expect. 1589*0fca6ea1SDimitry Andric << MatchTable::Comment("NumAddrSpace") 1590*0fca6ea1SDimitry Andric << MatchTable::IntValue(1, AddrSpaces.size()); 1591*0fca6ea1SDimitry Andric for (unsigned AS : AddrSpaces) 1592*0fca6ea1SDimitry Andric Table << MatchTable::Comment("AddrSpace") << MatchTable::ULEB128Value(AS); 1593*0fca6ea1SDimitry Andric 1594*0fca6ea1SDimitry Andric Table << MatchTable::LineBreak; 1595*0fca6ea1SDimitry Andric } 1596*0fca6ea1SDimitry Andric 1597*0fca6ea1SDimitry Andric //===- MemoryAlignmentPredicateMatcher ------------------------------------===// 1598*0fca6ea1SDimitry Andric 1599*0fca6ea1SDimitry Andric bool MemoryAlignmentPredicateMatcher::isIdentical( 1600*0fca6ea1SDimitry Andric const PredicateMatcher &B) const { 1601*0fca6ea1SDimitry Andric if (!InstructionPredicateMatcher::isIdentical(B)) 1602*0fca6ea1SDimitry Andric return false; 1603*0fca6ea1SDimitry Andric auto *Other = cast<MemoryAlignmentPredicateMatcher>(&B); 1604*0fca6ea1SDimitry Andric return MMOIdx == Other->MMOIdx && MinAlign == Other->MinAlign; 1605*0fca6ea1SDimitry Andric } 1606*0fca6ea1SDimitry Andric 1607*0fca6ea1SDimitry Andric void MemoryAlignmentPredicateMatcher::emitPredicateOpcodes( 1608*0fca6ea1SDimitry Andric MatchTable &Table, RuleMatcher &Rule) const { 1609*0fca6ea1SDimitry Andric // TODO: we could support more, just need to emit the right opcode or switch 1610*0fca6ea1SDimitry Andric // to log alignment. 1611*0fca6ea1SDimitry Andric assert(MinAlign < 256); 1612*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckMemoryAlignment") 1613*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1614*0fca6ea1SDimitry Andric << MatchTable::Comment("MMO") << MatchTable::ULEB128Value(MMOIdx) 1615*0fca6ea1SDimitry Andric << MatchTable::Comment("MinAlign") << MatchTable::IntValue(1, MinAlign) 1616*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1617*0fca6ea1SDimitry Andric } 1618*0fca6ea1SDimitry Andric 1619*0fca6ea1SDimitry Andric //===- MemoryVsLLTSizePredicateMatcher ------------------------------------===// 1620*0fca6ea1SDimitry Andric 1621*0fca6ea1SDimitry Andric bool MemoryVsLLTSizePredicateMatcher::isIdentical( 1622*0fca6ea1SDimitry Andric const PredicateMatcher &B) const { 1623*0fca6ea1SDimitry Andric return InstructionPredicateMatcher::isIdentical(B) && 1624*0fca6ea1SDimitry Andric MMOIdx == cast<MemoryVsLLTSizePredicateMatcher>(&B)->MMOIdx && 1625*0fca6ea1SDimitry Andric Relation == cast<MemoryVsLLTSizePredicateMatcher>(&B)->Relation && 1626*0fca6ea1SDimitry Andric OpIdx == cast<MemoryVsLLTSizePredicateMatcher>(&B)->OpIdx; 1627*0fca6ea1SDimitry Andric } 1628*0fca6ea1SDimitry Andric 1629*0fca6ea1SDimitry Andric void MemoryVsLLTSizePredicateMatcher::emitPredicateOpcodes( 1630*0fca6ea1SDimitry Andric MatchTable &Table, RuleMatcher &Rule) const { 1631*0fca6ea1SDimitry Andric Table << MatchTable::Opcode( 1632*0fca6ea1SDimitry Andric Relation == EqualTo ? "GIM_CheckMemorySizeEqualToLLT" 1633*0fca6ea1SDimitry Andric : Relation == GreaterThan ? "GIM_CheckMemorySizeGreaterThanLLT" 1634*0fca6ea1SDimitry Andric : "GIM_CheckMemorySizeLessThanLLT") 1635*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1636*0fca6ea1SDimitry Andric << MatchTable::Comment("MMO") << MatchTable::ULEB128Value(MMOIdx) 1637*0fca6ea1SDimitry Andric << MatchTable::Comment("OpIdx") << MatchTable::ULEB128Value(OpIdx) 1638*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1639*0fca6ea1SDimitry Andric } 1640*0fca6ea1SDimitry Andric 1641*0fca6ea1SDimitry Andric //===- VectorSplatImmPredicateMatcher -------------------------------------===// 1642*0fca6ea1SDimitry Andric 1643*0fca6ea1SDimitry Andric void VectorSplatImmPredicateMatcher::emitPredicateOpcodes( 1644*0fca6ea1SDimitry Andric MatchTable &Table, RuleMatcher &Rule) const { 1645*0fca6ea1SDimitry Andric if (Kind == AllOnes) 1646*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckIsBuildVectorAllOnes"); 1647*0fca6ea1SDimitry Andric else 1648*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckIsBuildVectorAllZeros"); 1649*0fca6ea1SDimitry Andric 1650*0fca6ea1SDimitry Andric Table << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID); 1651*0fca6ea1SDimitry Andric Table << MatchTable::LineBreak; 1652*0fca6ea1SDimitry Andric } 1653*0fca6ea1SDimitry Andric 1654*0fca6ea1SDimitry Andric //===- GenericInstructionPredicateMatcher ---------------------------------===// 1655*0fca6ea1SDimitry Andric 1656*0fca6ea1SDimitry Andric GenericInstructionPredicateMatcher::GenericInstructionPredicateMatcher( 1657*0fca6ea1SDimitry Andric unsigned InsnVarID, TreePredicateFn Predicate) 1658*0fca6ea1SDimitry Andric : GenericInstructionPredicateMatcher(InsnVarID, 1659*0fca6ea1SDimitry Andric getEnumNameForPredicate(Predicate)) {} 1660*0fca6ea1SDimitry Andric 1661*0fca6ea1SDimitry Andric bool GenericInstructionPredicateMatcher::isIdentical( 1662*0fca6ea1SDimitry Andric const PredicateMatcher &B) const { 1663*0fca6ea1SDimitry Andric return InstructionPredicateMatcher::isIdentical(B) && 1664*0fca6ea1SDimitry Andric EnumVal == 1665*0fca6ea1SDimitry Andric static_cast<const GenericInstructionPredicateMatcher &>(B).EnumVal; 1666*0fca6ea1SDimitry Andric } 1667*0fca6ea1SDimitry Andric void GenericInstructionPredicateMatcher::emitPredicateOpcodes( 1668*0fca6ea1SDimitry Andric MatchTable &Table, RuleMatcher &Rule) const { 1669*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckCxxInsnPredicate") 1670*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1671*0fca6ea1SDimitry Andric << MatchTable::Comment("FnId") << MatchTable::NamedValue(2, EnumVal) 1672*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1673*0fca6ea1SDimitry Andric } 1674*0fca6ea1SDimitry Andric 1675*0fca6ea1SDimitry Andric //===- MIFlagsInstructionPredicateMatcher ---------------------------------===// 1676*0fca6ea1SDimitry Andric 1677*0fca6ea1SDimitry Andric bool MIFlagsInstructionPredicateMatcher::isIdentical( 1678*0fca6ea1SDimitry Andric const PredicateMatcher &B) const { 1679*0fca6ea1SDimitry Andric if (!InstructionPredicateMatcher::isIdentical(B)) 1680*0fca6ea1SDimitry Andric return false; 1681*0fca6ea1SDimitry Andric const auto &Other = 1682*0fca6ea1SDimitry Andric static_cast<const MIFlagsInstructionPredicateMatcher &>(B); 1683*0fca6ea1SDimitry Andric return Flags == Other.Flags && CheckNot == Other.CheckNot; 1684*0fca6ea1SDimitry Andric } 1685*0fca6ea1SDimitry Andric 1686*0fca6ea1SDimitry Andric void MIFlagsInstructionPredicateMatcher::emitPredicateOpcodes( 1687*0fca6ea1SDimitry Andric MatchTable &Table, RuleMatcher &Rule) const { 1688*0fca6ea1SDimitry Andric Table << MatchTable::Opcode(CheckNot ? "GIM_MIFlagsNot" : "GIM_MIFlags") 1689*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1690*0fca6ea1SDimitry Andric << MatchTable::NamedValue(4, join(Flags, " | ")) 1691*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1692*0fca6ea1SDimitry Andric } 1693*0fca6ea1SDimitry Andric 1694*0fca6ea1SDimitry Andric //===- InstructionMatcher -------------------------------------------------===// 1695*0fca6ea1SDimitry Andric 1696*0fca6ea1SDimitry Andric OperandMatcher & 1697*0fca6ea1SDimitry Andric InstructionMatcher::addOperand(unsigned OpIdx, const std::string &SymbolicName, 1698*0fca6ea1SDimitry Andric unsigned AllocatedTemporariesBaseID) { 1699*0fca6ea1SDimitry Andric Operands.emplace_back(new OperandMatcher(*this, OpIdx, SymbolicName, 1700*0fca6ea1SDimitry Andric AllocatedTemporariesBaseID)); 1701*0fca6ea1SDimitry Andric if (!SymbolicName.empty()) 1702*0fca6ea1SDimitry Andric Rule.defineOperand(SymbolicName, *Operands.back()); 1703*0fca6ea1SDimitry Andric 1704*0fca6ea1SDimitry Andric return *Operands.back(); 1705*0fca6ea1SDimitry Andric } 1706*0fca6ea1SDimitry Andric 1707*0fca6ea1SDimitry Andric OperandMatcher &InstructionMatcher::getOperand(unsigned OpIdx) { 1708*0fca6ea1SDimitry Andric auto I = llvm::find_if(Operands, 1709*0fca6ea1SDimitry Andric [&OpIdx](const std::unique_ptr<OperandMatcher> &X) { 1710*0fca6ea1SDimitry Andric return X->getOpIdx() == OpIdx; 1711*0fca6ea1SDimitry Andric }); 1712*0fca6ea1SDimitry Andric if (I != Operands.end()) 1713*0fca6ea1SDimitry Andric return **I; 1714*0fca6ea1SDimitry Andric llvm_unreachable("Failed to lookup operand"); 1715*0fca6ea1SDimitry Andric } 1716*0fca6ea1SDimitry Andric 1717*0fca6ea1SDimitry Andric OperandMatcher &InstructionMatcher::addPhysRegInput(Record *Reg, unsigned OpIdx, 1718*0fca6ea1SDimitry Andric unsigned TempOpIdx) { 1719*0fca6ea1SDimitry Andric assert(SymbolicName.empty()); 1720*0fca6ea1SDimitry Andric OperandMatcher *OM = new OperandMatcher(*this, OpIdx, "", TempOpIdx); 1721*0fca6ea1SDimitry Andric Operands.emplace_back(OM); 1722*0fca6ea1SDimitry Andric Rule.definePhysRegOperand(Reg, *OM); 1723*0fca6ea1SDimitry Andric PhysRegInputs.emplace_back(Reg, OpIdx); 1724*0fca6ea1SDimitry Andric return *OM; 1725*0fca6ea1SDimitry Andric } 1726*0fca6ea1SDimitry Andric 1727*0fca6ea1SDimitry Andric void InstructionMatcher::emitPredicateOpcodes(MatchTable &Table, 1728*0fca6ea1SDimitry Andric RuleMatcher &Rule) { 1729*0fca6ea1SDimitry Andric if (NumOperandsCheck) 1730*0fca6ea1SDimitry Andric InstructionNumOperandsMatcher(InsnVarID, getNumOperands()) 1731*0fca6ea1SDimitry Andric .emitPredicateOpcodes(Table, Rule); 1732*0fca6ea1SDimitry Andric 1733*0fca6ea1SDimitry Andric // First emit all instruction level predicates need to be verified before we 1734*0fca6ea1SDimitry Andric // can verify operands. 1735*0fca6ea1SDimitry Andric emitFilteredPredicateListOpcodes( 1736*0fca6ea1SDimitry Andric [](const PredicateMatcher &P) { return !P.dependsOnOperands(); }, Table, 1737*0fca6ea1SDimitry Andric Rule); 1738*0fca6ea1SDimitry Andric 1739*0fca6ea1SDimitry Andric // Emit all operand constraints. 1740*0fca6ea1SDimitry Andric for (const auto &Operand : Operands) 1741*0fca6ea1SDimitry Andric Operand->emitPredicateOpcodes(Table, Rule); 1742*0fca6ea1SDimitry Andric 1743*0fca6ea1SDimitry Andric // All of the tablegen defined predicates should now be matched. Now emit 1744*0fca6ea1SDimitry Andric // any custom predicates that rely on all generated checks. 1745*0fca6ea1SDimitry Andric emitFilteredPredicateListOpcodes( 1746*0fca6ea1SDimitry Andric [](const PredicateMatcher &P) { return P.dependsOnOperands(); }, Table, 1747*0fca6ea1SDimitry Andric Rule); 1748*0fca6ea1SDimitry Andric } 1749*0fca6ea1SDimitry Andric 1750*0fca6ea1SDimitry Andric bool InstructionMatcher::isHigherPriorityThan(InstructionMatcher &B) { 1751*0fca6ea1SDimitry Andric // Instruction matchers involving more operands have higher priority. 1752*0fca6ea1SDimitry Andric if (Operands.size() > B.Operands.size()) 1753*0fca6ea1SDimitry Andric return true; 1754*0fca6ea1SDimitry Andric if (Operands.size() < B.Operands.size()) 1755*0fca6ea1SDimitry Andric return false; 1756*0fca6ea1SDimitry Andric 1757*0fca6ea1SDimitry Andric for (auto &&P : zip(predicates(), B.predicates())) { 1758*0fca6ea1SDimitry Andric auto L = static_cast<InstructionPredicateMatcher *>(std::get<0>(P).get()); 1759*0fca6ea1SDimitry Andric auto R = static_cast<InstructionPredicateMatcher *>(std::get<1>(P).get()); 1760*0fca6ea1SDimitry Andric if (L->isHigherPriorityThan(*R)) 1761*0fca6ea1SDimitry Andric return true; 1762*0fca6ea1SDimitry Andric if (R->isHigherPriorityThan(*L)) 1763*0fca6ea1SDimitry Andric return false; 1764*0fca6ea1SDimitry Andric } 1765*0fca6ea1SDimitry Andric 1766*0fca6ea1SDimitry Andric for (auto Operand : zip(Operands, B.Operands)) { 1767*0fca6ea1SDimitry Andric if (std::get<0>(Operand)->isHigherPriorityThan(*std::get<1>(Operand))) 1768*0fca6ea1SDimitry Andric return true; 1769*0fca6ea1SDimitry Andric if (std::get<1>(Operand)->isHigherPriorityThan(*std::get<0>(Operand))) 1770*0fca6ea1SDimitry Andric return false; 1771*0fca6ea1SDimitry Andric } 1772*0fca6ea1SDimitry Andric 1773*0fca6ea1SDimitry Andric return false; 1774*0fca6ea1SDimitry Andric } 1775*0fca6ea1SDimitry Andric 1776*0fca6ea1SDimitry Andric unsigned InstructionMatcher::countRendererFns() { 1777*0fca6ea1SDimitry Andric return std::accumulate( 1778*0fca6ea1SDimitry Andric predicates().begin(), predicates().end(), 0, 1779*0fca6ea1SDimitry Andric [](unsigned A, 1780*0fca6ea1SDimitry Andric const std::unique_ptr<PredicateMatcher> &Predicate) { 1781*0fca6ea1SDimitry Andric return A + Predicate->countRendererFns(); 1782*0fca6ea1SDimitry Andric }) + 1783*0fca6ea1SDimitry Andric std::accumulate( 1784*0fca6ea1SDimitry Andric Operands.begin(), Operands.end(), 0, 1785*0fca6ea1SDimitry Andric [](unsigned A, const std::unique_ptr<OperandMatcher> &Operand) { 1786*0fca6ea1SDimitry Andric return A + Operand->countRendererFns(); 1787*0fca6ea1SDimitry Andric }); 1788*0fca6ea1SDimitry Andric } 1789*0fca6ea1SDimitry Andric 1790*0fca6ea1SDimitry Andric void InstructionMatcher::optimize() { 1791*0fca6ea1SDimitry Andric SmallVector<std::unique_ptr<PredicateMatcher>, 8> Stash; 1792*0fca6ea1SDimitry Andric const auto &OpcMatcher = getOpcodeMatcher(); 1793*0fca6ea1SDimitry Andric 1794*0fca6ea1SDimitry Andric Stash.push_back(predicates_pop_front()); 1795*0fca6ea1SDimitry Andric if (Stash.back().get() == &OpcMatcher) { 1796*0fca6ea1SDimitry Andric if (NumOperandsCheck && OpcMatcher.isVariadicNumOperands() && 1797*0fca6ea1SDimitry Andric getNumOperands() != 0) 1798*0fca6ea1SDimitry Andric Stash.emplace_back( 1799*0fca6ea1SDimitry Andric new InstructionNumOperandsMatcher(InsnVarID, getNumOperands())); 1800*0fca6ea1SDimitry Andric NumOperandsCheck = false; 1801*0fca6ea1SDimitry Andric 1802*0fca6ea1SDimitry Andric for (auto &OM : Operands) 1803*0fca6ea1SDimitry Andric for (auto &OP : OM->predicates()) 1804*0fca6ea1SDimitry Andric if (isa<IntrinsicIDOperandMatcher>(OP)) { 1805*0fca6ea1SDimitry Andric Stash.push_back(std::move(OP)); 1806*0fca6ea1SDimitry Andric OM->eraseNullPredicates(); 1807*0fca6ea1SDimitry Andric break; 1808*0fca6ea1SDimitry Andric } 1809*0fca6ea1SDimitry Andric } 1810*0fca6ea1SDimitry Andric 1811*0fca6ea1SDimitry Andric if (InsnVarID > 0) { 1812*0fca6ea1SDimitry Andric assert(!Operands.empty() && "Nested instruction is expected to def a vreg"); 1813*0fca6ea1SDimitry Andric for (auto &OP : Operands[0]->predicates()) 1814*0fca6ea1SDimitry Andric OP.reset(); 1815*0fca6ea1SDimitry Andric Operands[0]->eraseNullPredicates(); 1816*0fca6ea1SDimitry Andric } 1817*0fca6ea1SDimitry Andric for (auto &OM : Operands) { 1818*0fca6ea1SDimitry Andric for (auto &OP : OM->predicates()) 1819*0fca6ea1SDimitry Andric if (isa<LLTOperandMatcher>(OP)) 1820*0fca6ea1SDimitry Andric Stash.push_back(std::move(OP)); 1821*0fca6ea1SDimitry Andric OM->eraseNullPredicates(); 1822*0fca6ea1SDimitry Andric } 1823*0fca6ea1SDimitry Andric while (!Stash.empty()) 1824*0fca6ea1SDimitry Andric prependPredicate(Stash.pop_back_val()); 1825*0fca6ea1SDimitry Andric } 1826*0fca6ea1SDimitry Andric 1827*0fca6ea1SDimitry Andric //===- InstructionOperandMatcher ------------------------------------------===// 1828*0fca6ea1SDimitry Andric 1829*0fca6ea1SDimitry Andric void InstructionOperandMatcher::emitCaptureOpcodes(MatchTable &Table, 1830*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1831*0fca6ea1SDimitry Andric const unsigned NewInsnVarID = InsnMatcher->getInsnVarID(); 1832*0fca6ea1SDimitry Andric const bool IgnoreCopies = Flags & GISF_IgnoreCopies; 1833*0fca6ea1SDimitry Andric Table << MatchTable::Opcode(IgnoreCopies ? "GIM_RecordInsnIgnoreCopies" 1834*0fca6ea1SDimitry Andric : "GIM_RecordInsn") 1835*0fca6ea1SDimitry Andric << MatchTable::Comment("DefineMI") 1836*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(NewInsnVarID) << MatchTable::Comment("MI") 1837*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(getInsnVarID()) 1838*0fca6ea1SDimitry Andric << MatchTable::Comment("OpIdx") << MatchTable::ULEB128Value(getOpIdx()) 1839*0fca6ea1SDimitry Andric << MatchTable::Comment("MIs[" + llvm::to_string(NewInsnVarID) + "]") 1840*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1841*0fca6ea1SDimitry Andric } 1842*0fca6ea1SDimitry Andric 1843*0fca6ea1SDimitry Andric bool InstructionOperandMatcher::isHigherPriorityThan( 1844*0fca6ea1SDimitry Andric const OperandPredicateMatcher &B) const { 1845*0fca6ea1SDimitry Andric if (OperandPredicateMatcher::isHigherPriorityThan(B)) 1846*0fca6ea1SDimitry Andric return true; 1847*0fca6ea1SDimitry Andric if (B.OperandPredicateMatcher::isHigherPriorityThan(*this)) 1848*0fca6ea1SDimitry Andric return false; 1849*0fca6ea1SDimitry Andric 1850*0fca6ea1SDimitry Andric if (const InstructionOperandMatcher *BP = 1851*0fca6ea1SDimitry Andric dyn_cast<InstructionOperandMatcher>(&B)) 1852*0fca6ea1SDimitry Andric if (InsnMatcher->isHigherPriorityThan(*BP->InsnMatcher)) 1853*0fca6ea1SDimitry Andric return true; 1854*0fca6ea1SDimitry Andric return false; 1855*0fca6ea1SDimitry Andric } 1856*0fca6ea1SDimitry Andric 1857*0fca6ea1SDimitry Andric //===- OperandRenderer ----------------------------------------------------===// 1858*0fca6ea1SDimitry Andric 1859*0fca6ea1SDimitry Andric OperandRenderer::~OperandRenderer() {} 1860*0fca6ea1SDimitry Andric 1861*0fca6ea1SDimitry Andric //===- CopyRenderer -------------------------------------------------------===// 1862*0fca6ea1SDimitry Andric 1863*0fca6ea1SDimitry Andric void CopyRenderer::emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule, 1864*0fca6ea1SDimitry Andric unsigned NewInsnID, unsigned OldInsnID, 1865*0fca6ea1SDimitry Andric unsigned OpIdx, StringRef Name) { 1866*0fca6ea1SDimitry Andric if (NewInsnID == 0 && OldInsnID == 0) { 1867*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_RootToRootCopy"); 1868*0fca6ea1SDimitry Andric } else { 1869*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_Copy") << MatchTable::Comment("NewInsnID") 1870*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(NewInsnID) 1871*0fca6ea1SDimitry Andric << MatchTable::Comment("OldInsnID") 1872*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OldInsnID); 1873*0fca6ea1SDimitry Andric } 1874*0fca6ea1SDimitry Andric 1875*0fca6ea1SDimitry Andric Table << MatchTable::Comment("OpIdx") << MatchTable::ULEB128Value(OpIdx) 1876*0fca6ea1SDimitry Andric << MatchTable::Comment(Name) << MatchTable::LineBreak; 1877*0fca6ea1SDimitry Andric } 1878*0fca6ea1SDimitry Andric 1879*0fca6ea1SDimitry Andric void CopyRenderer::emitRenderOpcodes(MatchTable &Table, 1880*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1881*0fca6ea1SDimitry Andric const OperandMatcher &Operand = Rule.getOperandMatcher(SymbolicName); 1882*0fca6ea1SDimitry Andric unsigned OldInsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher()); 1883*0fca6ea1SDimitry Andric emitRenderOpcodes(Table, Rule, NewInsnID, OldInsnVarID, Operand.getOpIdx(), 1884*0fca6ea1SDimitry Andric SymbolicName); 1885*0fca6ea1SDimitry Andric } 1886*0fca6ea1SDimitry Andric 1887*0fca6ea1SDimitry Andric //===- CopyPhysRegRenderer ------------------------------------------------===// 1888*0fca6ea1SDimitry Andric 1889*0fca6ea1SDimitry Andric void CopyPhysRegRenderer::emitRenderOpcodes(MatchTable &Table, 1890*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1891*0fca6ea1SDimitry Andric const OperandMatcher &Operand = Rule.getPhysRegOperandMatcher(PhysReg); 1892*0fca6ea1SDimitry Andric unsigned OldInsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher()); 1893*0fca6ea1SDimitry Andric CopyRenderer::emitRenderOpcodes(Table, Rule, NewInsnID, OldInsnVarID, 1894*0fca6ea1SDimitry Andric Operand.getOpIdx(), PhysReg->getName()); 1895*0fca6ea1SDimitry Andric } 1896*0fca6ea1SDimitry Andric 1897*0fca6ea1SDimitry Andric //===- CopyOrAddZeroRegRenderer -------------------------------------------===// 1898*0fca6ea1SDimitry Andric 1899*0fca6ea1SDimitry Andric void CopyOrAddZeroRegRenderer::emitRenderOpcodes(MatchTable &Table, 1900*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1901*0fca6ea1SDimitry Andric const OperandMatcher &Operand = Rule.getOperandMatcher(SymbolicName); 1902*0fca6ea1SDimitry Andric unsigned OldInsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher()); 1903*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_CopyOrAddZeroReg") 1904*0fca6ea1SDimitry Andric << MatchTable::Comment("NewInsnID") 1905*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(NewInsnID) 1906*0fca6ea1SDimitry Andric << MatchTable::Comment("OldInsnID") 1907*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OldInsnVarID) 1908*0fca6ea1SDimitry Andric << MatchTable::Comment("OpIdx") 1909*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(Operand.getOpIdx()) 1910*0fca6ea1SDimitry Andric << MatchTable::NamedValue( 1911*0fca6ea1SDimitry Andric 2, 1912*0fca6ea1SDimitry Andric (ZeroRegisterDef->getValue("Namespace") 1913*0fca6ea1SDimitry Andric ? ZeroRegisterDef->getValueAsString("Namespace") 1914*0fca6ea1SDimitry Andric : ""), 1915*0fca6ea1SDimitry Andric ZeroRegisterDef->getName()) 1916*0fca6ea1SDimitry Andric << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak; 1917*0fca6ea1SDimitry Andric } 1918*0fca6ea1SDimitry Andric 1919*0fca6ea1SDimitry Andric //===- CopyConstantAsImmRenderer ------------------------------------------===// 1920*0fca6ea1SDimitry Andric 1921*0fca6ea1SDimitry Andric void CopyConstantAsImmRenderer::emitRenderOpcodes(MatchTable &Table, 1922*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1923*0fca6ea1SDimitry Andric InstructionMatcher &InsnMatcher = Rule.getInstructionMatcher(SymbolicName); 1924*0fca6ea1SDimitry Andric unsigned OldInsnVarID = Rule.getInsnVarID(InsnMatcher); 1925*0fca6ea1SDimitry Andric Table << MatchTable::Opcode(Signed ? "GIR_CopyConstantAsSImm" 1926*0fca6ea1SDimitry Andric : "GIR_CopyConstantAsUImm") 1927*0fca6ea1SDimitry Andric << MatchTable::Comment("NewInsnID") 1928*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(NewInsnID) 1929*0fca6ea1SDimitry Andric << MatchTable::Comment("OldInsnID") 1930*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OldInsnVarID) 1931*0fca6ea1SDimitry Andric << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak; 1932*0fca6ea1SDimitry Andric } 1933*0fca6ea1SDimitry Andric 1934*0fca6ea1SDimitry Andric //===- CopyFConstantAsFPImmRenderer ---------------------------------------===// 1935*0fca6ea1SDimitry Andric 1936*0fca6ea1SDimitry Andric void CopyFConstantAsFPImmRenderer::emitRenderOpcodes(MatchTable &Table, 1937*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1938*0fca6ea1SDimitry Andric InstructionMatcher &InsnMatcher = Rule.getInstructionMatcher(SymbolicName); 1939*0fca6ea1SDimitry Andric unsigned OldInsnVarID = Rule.getInsnVarID(InsnMatcher); 1940*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_CopyFConstantAsFPImm") 1941*0fca6ea1SDimitry Andric << MatchTable::Comment("NewInsnID") 1942*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(NewInsnID) 1943*0fca6ea1SDimitry Andric << MatchTable::Comment("OldInsnID") 1944*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OldInsnVarID) 1945*0fca6ea1SDimitry Andric << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak; 1946*0fca6ea1SDimitry Andric } 1947*0fca6ea1SDimitry Andric 1948*0fca6ea1SDimitry Andric //===- CopySubRegRenderer -------------------------------------------------===// 1949*0fca6ea1SDimitry Andric 1950*0fca6ea1SDimitry Andric void CopySubRegRenderer::emitRenderOpcodes(MatchTable &Table, 1951*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1952*0fca6ea1SDimitry Andric const OperandMatcher &Operand = Rule.getOperandMatcher(SymbolicName); 1953*0fca6ea1SDimitry Andric unsigned OldInsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher()); 1954*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_CopySubReg") 1955*0fca6ea1SDimitry Andric << MatchTable::Comment("NewInsnID") 1956*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(NewInsnID) 1957*0fca6ea1SDimitry Andric << MatchTable::Comment("OldInsnID") 1958*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OldInsnVarID) 1959*0fca6ea1SDimitry Andric << MatchTable::Comment("OpIdx") 1960*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(Operand.getOpIdx()) 1961*0fca6ea1SDimitry Andric << MatchTable::Comment("SubRegIdx") 1962*0fca6ea1SDimitry Andric << MatchTable::IntValue(2, SubReg->EnumValue) 1963*0fca6ea1SDimitry Andric << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak; 1964*0fca6ea1SDimitry Andric } 1965*0fca6ea1SDimitry Andric 1966*0fca6ea1SDimitry Andric //===- AddRegisterRenderer ------------------------------------------------===// 1967*0fca6ea1SDimitry Andric 1968*0fca6ea1SDimitry Andric void AddRegisterRenderer::emitRenderOpcodes(MatchTable &Table, 1969*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1970*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_AddRegister") 1971*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID); 1972*0fca6ea1SDimitry Andric if (RegisterDef->getName() != "zero_reg") { 1973*0fca6ea1SDimitry Andric Table << MatchTable::NamedValue( 1974*0fca6ea1SDimitry Andric 2, 1975*0fca6ea1SDimitry Andric (RegisterDef->getValue("Namespace") 1976*0fca6ea1SDimitry Andric ? RegisterDef->getValueAsString("Namespace") 1977*0fca6ea1SDimitry Andric : ""), 1978*0fca6ea1SDimitry Andric RegisterDef->getName()); 1979*0fca6ea1SDimitry Andric } else { 1980*0fca6ea1SDimitry Andric Table << MatchTable::NamedValue(2, Target.getRegNamespace(), "NoRegister"); 1981*0fca6ea1SDimitry Andric } 1982*0fca6ea1SDimitry Andric Table << MatchTable::Comment("AddRegisterRegFlags"); 1983*0fca6ea1SDimitry Andric 1984*0fca6ea1SDimitry Andric // TODO: This is encoded as a 64-bit element, but only 16 or 32-bits are 1985*0fca6ea1SDimitry Andric // really needed for a physical register reference. We can pack the 1986*0fca6ea1SDimitry Andric // register and flags in a single field. 1987*0fca6ea1SDimitry Andric if (IsDef) 1988*0fca6ea1SDimitry Andric Table << MatchTable::NamedValue(2, "RegState::Define"); 1989*0fca6ea1SDimitry Andric else 1990*0fca6ea1SDimitry Andric Table << MatchTable::IntValue(2, 0); 1991*0fca6ea1SDimitry Andric Table << MatchTable::LineBreak; 1992*0fca6ea1SDimitry Andric } 1993*0fca6ea1SDimitry Andric 1994*0fca6ea1SDimitry Andric //===- TempRegRenderer ----------------------------------------------------===// 1995*0fca6ea1SDimitry Andric 1996*0fca6ea1SDimitry Andric void TempRegRenderer::emitRenderOpcodes(MatchTable &Table, 1997*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 1998*0fca6ea1SDimitry Andric const bool NeedsFlags = (SubRegIdx || IsDef); 1999*0fca6ea1SDimitry Andric if (SubRegIdx) { 2000*0fca6ea1SDimitry Andric assert(!IsDef); 2001*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_AddTempSubRegister"); 2002*0fca6ea1SDimitry Andric } else 2003*0fca6ea1SDimitry Andric Table << MatchTable::Opcode(NeedsFlags ? "GIR_AddTempRegister" 2004*0fca6ea1SDimitry Andric : "GIR_AddSimpleTempRegister"); 2005*0fca6ea1SDimitry Andric 2006*0fca6ea1SDimitry Andric Table << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID) 2007*0fca6ea1SDimitry Andric << MatchTable::Comment("TempRegID") 2008*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(TempRegID); 2009*0fca6ea1SDimitry Andric 2010*0fca6ea1SDimitry Andric if (!NeedsFlags) { 2011*0fca6ea1SDimitry Andric Table << MatchTable::LineBreak; 2012*0fca6ea1SDimitry Andric return; 2013*0fca6ea1SDimitry Andric } 2014*0fca6ea1SDimitry Andric 2015*0fca6ea1SDimitry Andric Table << MatchTable::Comment("TempRegFlags"); 2016*0fca6ea1SDimitry Andric if (IsDef) { 2017*0fca6ea1SDimitry Andric SmallString<32> RegFlags; 2018*0fca6ea1SDimitry Andric RegFlags += "RegState::Define"; 2019*0fca6ea1SDimitry Andric if (IsDead) 2020*0fca6ea1SDimitry Andric RegFlags += "|RegState::Dead"; 2021*0fca6ea1SDimitry Andric Table << MatchTable::NamedValue(2, RegFlags); 2022*0fca6ea1SDimitry Andric } else 2023*0fca6ea1SDimitry Andric Table << MatchTable::IntValue(2, 0); 2024*0fca6ea1SDimitry Andric 2025*0fca6ea1SDimitry Andric if (SubRegIdx) 2026*0fca6ea1SDimitry Andric Table << MatchTable::NamedValue(2, SubRegIdx->getQualifiedName()); 2027*0fca6ea1SDimitry Andric Table << MatchTable::LineBreak; 2028*0fca6ea1SDimitry Andric } 2029*0fca6ea1SDimitry Andric 2030*0fca6ea1SDimitry Andric //===- ImmRenderer --------------------------------------------------------===// 2031*0fca6ea1SDimitry Andric 2032*0fca6ea1SDimitry Andric void ImmRenderer::emitAddImm(MatchTable &Table, RuleMatcher &RM, 2033*0fca6ea1SDimitry Andric unsigned InsnID, int64_t Imm, StringRef ImmName) { 2034*0fca6ea1SDimitry Andric const bool IsInt8 = isInt<8>(Imm); 2035*0fca6ea1SDimitry Andric 2036*0fca6ea1SDimitry Andric Table << MatchTable::Opcode(IsInt8 ? "GIR_AddImm8" : "GIR_AddImm") 2037*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID) 2038*0fca6ea1SDimitry Andric << MatchTable::Comment(ImmName) 2039*0fca6ea1SDimitry Andric << MatchTable::IntValue(IsInt8 ? 1 : 8, Imm) << MatchTable::LineBreak; 2040*0fca6ea1SDimitry Andric } 2041*0fca6ea1SDimitry Andric 2042*0fca6ea1SDimitry Andric void ImmRenderer::emitRenderOpcodes(MatchTable &Table, 2043*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 2044*0fca6ea1SDimitry Andric if (CImmLLT) { 2045*0fca6ea1SDimitry Andric assert(Table.isCombiner() && 2046*0fca6ea1SDimitry Andric "ConstantInt immediate are only for combiners!"); 2047*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_AddCImm") << MatchTable::Comment("InsnID") 2048*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(InsnID) << MatchTable::Comment("Type") 2049*0fca6ea1SDimitry Andric << *CImmLLT << MatchTable::Comment("Imm") 2050*0fca6ea1SDimitry Andric << MatchTable::IntValue(8, Imm) << MatchTable::LineBreak; 2051*0fca6ea1SDimitry Andric } else 2052*0fca6ea1SDimitry Andric emitAddImm(Table, Rule, InsnID, Imm); 2053*0fca6ea1SDimitry Andric } 2054*0fca6ea1SDimitry Andric 2055*0fca6ea1SDimitry Andric //===- SubRegIndexRenderer ------------------------------------------------===// 2056*0fca6ea1SDimitry Andric 2057*0fca6ea1SDimitry Andric void SubRegIndexRenderer::emitRenderOpcodes(MatchTable &Table, 2058*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 2059*0fca6ea1SDimitry Andric ImmRenderer::emitAddImm(Table, Rule, InsnID, SubRegIdx->EnumValue, 2060*0fca6ea1SDimitry Andric "SubRegIndex"); 2061*0fca6ea1SDimitry Andric } 2062*0fca6ea1SDimitry Andric 2063*0fca6ea1SDimitry Andric //===- RenderComplexPatternOperand ----------------------------------------===// 2064*0fca6ea1SDimitry Andric 2065*0fca6ea1SDimitry Andric void RenderComplexPatternOperand::emitRenderOpcodes(MatchTable &Table, 2066*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 2067*0fca6ea1SDimitry Andric Table << MatchTable::Opcode( 2068*0fca6ea1SDimitry Andric SubOperand ? (SubReg ? "GIR_ComplexSubOperandSubRegRenderer" 2069*0fca6ea1SDimitry Andric : "GIR_ComplexSubOperandRenderer") 2070*0fca6ea1SDimitry Andric : "GIR_ComplexRenderer") 2071*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID) 2072*0fca6ea1SDimitry Andric << MatchTable::Comment("RendererID") 2073*0fca6ea1SDimitry Andric << MatchTable::IntValue(2, RendererID); 2074*0fca6ea1SDimitry Andric if (SubOperand) 2075*0fca6ea1SDimitry Andric Table << MatchTable::Comment("SubOperand") 2076*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(*SubOperand); 2077*0fca6ea1SDimitry Andric if (SubReg) 2078*0fca6ea1SDimitry Andric Table << MatchTable::Comment("SubRegIdx") 2079*0fca6ea1SDimitry Andric << MatchTable::IntValue(2, SubReg->EnumValue); 2080*0fca6ea1SDimitry Andric Table << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak; 2081*0fca6ea1SDimitry Andric } 2082*0fca6ea1SDimitry Andric 2083*0fca6ea1SDimitry Andric //===- IntrinsicIDRenderer ------------------------------------------------===// 2084*0fca6ea1SDimitry Andric 2085*0fca6ea1SDimitry Andric void IntrinsicIDRenderer::emitRenderOpcodes(MatchTable &Table, 2086*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 2087*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_AddIntrinsicID") << MatchTable::Comment("MI") 2088*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(InsnID) 2089*0fca6ea1SDimitry Andric << MatchTable::NamedValue(2, "Intrinsic::" + II->EnumName) 2090*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 2091*0fca6ea1SDimitry Andric } 2092*0fca6ea1SDimitry Andric 2093*0fca6ea1SDimitry Andric //===- CustomRenderer -----------------------------------------------------===// 2094*0fca6ea1SDimitry Andric 2095*0fca6ea1SDimitry Andric void CustomRenderer::emitRenderOpcodes(MatchTable &Table, 2096*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 2097*0fca6ea1SDimitry Andric InstructionMatcher &InsnMatcher = Rule.getInstructionMatcher(SymbolicName); 2098*0fca6ea1SDimitry Andric unsigned OldInsnVarID = Rule.getInsnVarID(InsnMatcher); 2099*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_CustomRenderer") 2100*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID) 2101*0fca6ea1SDimitry Andric << MatchTable::Comment("OldInsnID") 2102*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OldInsnVarID) 2103*0fca6ea1SDimitry Andric << MatchTable::Comment("Renderer") 2104*0fca6ea1SDimitry Andric << MatchTable::NamedValue( 2105*0fca6ea1SDimitry Andric 2, "GICR_" + Renderer.getValueAsString("RendererFn").str()) 2106*0fca6ea1SDimitry Andric << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak; 2107*0fca6ea1SDimitry Andric } 2108*0fca6ea1SDimitry Andric 2109*0fca6ea1SDimitry Andric //===- CustomOperandRenderer ----------------------------------------------===// 2110*0fca6ea1SDimitry Andric 2111*0fca6ea1SDimitry Andric void CustomOperandRenderer::emitRenderOpcodes(MatchTable &Table, 2112*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 2113*0fca6ea1SDimitry Andric const OperandMatcher &OpdMatcher = Rule.getOperandMatcher(SymbolicName); 2114*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_CustomOperandRenderer") 2115*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID) 2116*0fca6ea1SDimitry Andric << MatchTable::Comment("OldInsnID") 2117*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OpdMatcher.getInsnVarID()) 2118*0fca6ea1SDimitry Andric << MatchTable::Comment("OpIdx") 2119*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OpdMatcher.getOpIdx()) 2120*0fca6ea1SDimitry Andric << MatchTable::Comment("OperandRenderer") 2121*0fca6ea1SDimitry Andric << MatchTable::NamedValue( 2122*0fca6ea1SDimitry Andric 2, "GICR_" + Renderer.getValueAsString("RendererFn").str()) 2123*0fca6ea1SDimitry Andric << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak; 2124*0fca6ea1SDimitry Andric } 2125*0fca6ea1SDimitry Andric 2126*0fca6ea1SDimitry Andric //===- BuildMIAction ------------------------------------------------------===// 2127*0fca6ea1SDimitry Andric 2128*0fca6ea1SDimitry Andric bool BuildMIAction::canMutate(RuleMatcher &Rule, 2129*0fca6ea1SDimitry Andric const InstructionMatcher *Insn) const { 2130*0fca6ea1SDimitry Andric if (!Insn) 2131*0fca6ea1SDimitry Andric return false; 2132*0fca6ea1SDimitry Andric 2133*0fca6ea1SDimitry Andric if (OperandRenderers.size() != Insn->getNumOperands()) 2134*0fca6ea1SDimitry Andric return false; 2135*0fca6ea1SDimitry Andric 2136*0fca6ea1SDimitry Andric for (const auto &Renderer : enumerate(OperandRenderers)) { 2137*0fca6ea1SDimitry Andric if (const auto *Copy = dyn_cast<CopyRenderer>(&*Renderer.value())) { 2138*0fca6ea1SDimitry Andric const OperandMatcher &OM = 2139*0fca6ea1SDimitry Andric Rule.getOperandMatcher(Copy->getSymbolicName()); 2140*0fca6ea1SDimitry Andric if (Insn != &OM.getInstructionMatcher() || 2141*0fca6ea1SDimitry Andric OM.getOpIdx() != Renderer.index()) 2142*0fca6ea1SDimitry Andric return false; 2143*0fca6ea1SDimitry Andric } else 2144*0fca6ea1SDimitry Andric return false; 2145*0fca6ea1SDimitry Andric } 2146*0fca6ea1SDimitry Andric 2147*0fca6ea1SDimitry Andric return true; 2148*0fca6ea1SDimitry Andric } 2149*0fca6ea1SDimitry Andric 2150*0fca6ea1SDimitry Andric void BuildMIAction::chooseInsnToMutate(RuleMatcher &Rule) { 2151*0fca6ea1SDimitry Andric for (auto *MutateCandidate : Rule.mutatable_insns()) { 2152*0fca6ea1SDimitry Andric if (canMutate(Rule, MutateCandidate)) { 2153*0fca6ea1SDimitry Andric // Take the first one we're offered that we're able to mutate. 2154*0fca6ea1SDimitry Andric Rule.reserveInsnMatcherForMutation(MutateCandidate); 2155*0fca6ea1SDimitry Andric Matched = MutateCandidate; 2156*0fca6ea1SDimitry Andric return; 2157*0fca6ea1SDimitry Andric } 2158*0fca6ea1SDimitry Andric } 2159*0fca6ea1SDimitry Andric } 2160*0fca6ea1SDimitry Andric 2161*0fca6ea1SDimitry Andric void BuildMIAction::emitActionOpcodes(MatchTable &Table, 2162*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 2163*0fca6ea1SDimitry Andric const auto AddMIFlags = [&]() { 2164*0fca6ea1SDimitry Andric for (const InstructionMatcher *IM : CopiedFlags) { 2165*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_CopyMIFlags") 2166*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID) 2167*0fca6ea1SDimitry Andric << MatchTable::Comment("OldInsnID") 2168*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(IM->getInsnVarID()) 2169*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 2170*0fca6ea1SDimitry Andric } 2171*0fca6ea1SDimitry Andric 2172*0fca6ea1SDimitry Andric if (!SetFlags.empty()) { 2173*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_SetMIFlags") 2174*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID) 2175*0fca6ea1SDimitry Andric << MatchTable::NamedValue(4, join(SetFlags, " | ")) 2176*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 2177*0fca6ea1SDimitry Andric } 2178*0fca6ea1SDimitry Andric 2179*0fca6ea1SDimitry Andric if (!UnsetFlags.empty()) { 2180*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_UnsetMIFlags") 2181*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID) 2182*0fca6ea1SDimitry Andric << MatchTable::NamedValue(4, join(UnsetFlags, " | ")) 2183*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 2184*0fca6ea1SDimitry Andric } 2185*0fca6ea1SDimitry Andric }; 2186*0fca6ea1SDimitry Andric 2187*0fca6ea1SDimitry Andric if (Matched) { 2188*0fca6ea1SDimitry Andric assert(canMutate(Rule, Matched) && 2189*0fca6ea1SDimitry Andric "Arranged to mutate an insn that isn't mutatable"); 2190*0fca6ea1SDimitry Andric 2191*0fca6ea1SDimitry Andric unsigned RecycleInsnID = Rule.getInsnVarID(*Matched); 2192*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_MutateOpcode") 2193*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID) 2194*0fca6ea1SDimitry Andric << MatchTable::Comment("RecycleInsnID") 2195*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(RecycleInsnID) 2196*0fca6ea1SDimitry Andric << MatchTable::Comment("Opcode") 2197*0fca6ea1SDimitry Andric << MatchTable::NamedValue(2, I->Namespace, I->TheDef->getName()) 2198*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 2199*0fca6ea1SDimitry Andric 2200*0fca6ea1SDimitry Andric if (!I->ImplicitDefs.empty() || !I->ImplicitUses.empty()) { 2201*0fca6ea1SDimitry Andric for (auto *Def : I->ImplicitDefs) { 2202*0fca6ea1SDimitry Andric auto Namespace = Def->getValue("Namespace") 2203*0fca6ea1SDimitry Andric ? Def->getValueAsString("Namespace") 2204*0fca6ea1SDimitry Andric : ""; 2205*0fca6ea1SDimitry Andric const bool IsDead = DeadImplicitDefs.contains(Def); 2206*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_AddImplicitDef") 2207*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") 2208*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(InsnID) 2209*0fca6ea1SDimitry Andric << MatchTable::NamedValue(2, Namespace, Def->getName()) 2210*0fca6ea1SDimitry Andric << (IsDead ? MatchTable::NamedValue(2, "RegState", "Dead") 2211*0fca6ea1SDimitry Andric : MatchTable::IntValue(2, 0)) 2212*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 2213*0fca6ea1SDimitry Andric } 2214*0fca6ea1SDimitry Andric for (auto *Use : I->ImplicitUses) { 2215*0fca6ea1SDimitry Andric auto Namespace = Use->getValue("Namespace") 2216*0fca6ea1SDimitry Andric ? Use->getValueAsString("Namespace") 2217*0fca6ea1SDimitry Andric : ""; 2218*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_AddImplicitUse") 2219*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") 2220*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(InsnID) 2221*0fca6ea1SDimitry Andric << MatchTable::NamedValue(2, Namespace, Use->getName()) 2222*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 2223*0fca6ea1SDimitry Andric } 2224*0fca6ea1SDimitry Andric } 2225*0fca6ea1SDimitry Andric 2226*0fca6ea1SDimitry Andric AddMIFlags(); 2227*0fca6ea1SDimitry Andric 2228*0fca6ea1SDimitry Andric // Mark the mutated instruction as erased. 2229*0fca6ea1SDimitry Andric Rule.tryEraseInsnID(RecycleInsnID); 2230*0fca6ea1SDimitry Andric return; 2231*0fca6ea1SDimitry Andric } 2232*0fca6ea1SDimitry Andric 2233*0fca6ea1SDimitry Andric // TODO: Simple permutation looks like it could be almost as common as 2234*0fca6ea1SDimitry Andric // mutation due to commutative operations. 2235*0fca6ea1SDimitry Andric 2236*0fca6ea1SDimitry Andric if (InsnID == 0) { 2237*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_BuildRootMI"); 2238*0fca6ea1SDimitry Andric } else { 2239*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_BuildMI") << MatchTable::Comment("InsnID") 2240*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(InsnID); 2241*0fca6ea1SDimitry Andric } 2242*0fca6ea1SDimitry Andric 2243*0fca6ea1SDimitry Andric Table << MatchTable::Comment("Opcode") 2244*0fca6ea1SDimitry Andric << MatchTable::NamedValue(2, I->Namespace, I->TheDef->getName()) 2245*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 2246*0fca6ea1SDimitry Andric 2247*0fca6ea1SDimitry Andric for (const auto &Renderer : OperandRenderers) 2248*0fca6ea1SDimitry Andric Renderer->emitRenderOpcodes(Table, Rule); 2249*0fca6ea1SDimitry Andric 2250*0fca6ea1SDimitry Andric for (auto [OpIdx, Def] : enumerate(I->ImplicitDefs)) { 2251*0fca6ea1SDimitry Andric auto Namespace = 2252*0fca6ea1SDimitry Andric Def->getValue("Namespace") ? Def->getValueAsString("Namespace") : ""; 2253*0fca6ea1SDimitry Andric if (DeadImplicitDefs.contains(Def)) { 2254*0fca6ea1SDimitry Andric Table 2255*0fca6ea1SDimitry Andric << MatchTable::Opcode("GIR_SetImplicitDefDead") 2256*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID) 2257*0fca6ea1SDimitry Andric << MatchTable::Comment( 2258*0fca6ea1SDimitry Andric ("OpIdx for " + Namespace + "::" + Def->getName() + "").str()) 2259*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OpIdx) << MatchTable::LineBreak; 2260*0fca6ea1SDimitry Andric } 2261*0fca6ea1SDimitry Andric } 2262*0fca6ea1SDimitry Andric 2263*0fca6ea1SDimitry Andric if (I->mayLoad || I->mayStore) { 2264*0fca6ea1SDimitry Andric // Emit the ID's for all the instructions that are matched by this rule. 2265*0fca6ea1SDimitry Andric // TODO: Limit this to matched instructions that mayLoad/mayStore or have 2266*0fca6ea1SDimitry Andric // some other means of having a memoperand. Also limit this to 2267*0fca6ea1SDimitry Andric // emitted instructions that expect to have a memoperand too. For 2268*0fca6ea1SDimitry Andric // example, (G_SEXT (G_LOAD x)) that results in separate load and 2269*0fca6ea1SDimitry Andric // sign-extend instructions shouldn't put the memoperand on the 2270*0fca6ea1SDimitry Andric // sign-extend since it has no effect there. 2271*0fca6ea1SDimitry Andric 2272*0fca6ea1SDimitry Andric std::vector<unsigned> MergeInsnIDs; 2273*0fca6ea1SDimitry Andric for (const auto &IDMatcherPair : Rule.defined_insn_vars()) 2274*0fca6ea1SDimitry Andric MergeInsnIDs.push_back(IDMatcherPair.second); 2275*0fca6ea1SDimitry Andric llvm::sort(MergeInsnIDs); 2276*0fca6ea1SDimitry Andric 2277*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_MergeMemOperands") 2278*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID) 2279*0fca6ea1SDimitry Andric << MatchTable::Comment("NumInsns") 2280*0fca6ea1SDimitry Andric << MatchTable::IntValue(1, MergeInsnIDs.size()) 2281*0fca6ea1SDimitry Andric << MatchTable::Comment("MergeInsnID's"); 2282*0fca6ea1SDimitry Andric for (const auto &MergeInsnID : MergeInsnIDs) 2283*0fca6ea1SDimitry Andric Table << MatchTable::ULEB128Value(MergeInsnID); 2284*0fca6ea1SDimitry Andric Table << MatchTable::LineBreak; 2285*0fca6ea1SDimitry Andric } 2286*0fca6ea1SDimitry Andric 2287*0fca6ea1SDimitry Andric AddMIFlags(); 2288*0fca6ea1SDimitry Andric } 2289*0fca6ea1SDimitry Andric 2290*0fca6ea1SDimitry Andric //===- BuildConstantAction ------------------------------------------------===// 2291*0fca6ea1SDimitry Andric 2292*0fca6ea1SDimitry Andric void BuildConstantAction::emitActionOpcodes(MatchTable &Table, 2293*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 2294*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_BuildConstant") 2295*0fca6ea1SDimitry Andric << MatchTable::Comment("TempRegID") 2296*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(TempRegID) << MatchTable::Comment("Val") 2297*0fca6ea1SDimitry Andric << MatchTable::IntValue(8, Val) << MatchTable::LineBreak; 2298*0fca6ea1SDimitry Andric } 2299*0fca6ea1SDimitry Andric 2300*0fca6ea1SDimitry Andric //===- EraseInstAction ----------------------------------------------------===// 2301*0fca6ea1SDimitry Andric 2302*0fca6ea1SDimitry Andric void EraseInstAction::emitActionOpcodes(MatchTable &Table, 2303*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 2304*0fca6ea1SDimitry Andric // Avoid erasing the same inst twice. 2305*0fca6ea1SDimitry Andric if (!Rule.tryEraseInsnID(InsnID)) 2306*0fca6ea1SDimitry Andric return; 2307*0fca6ea1SDimitry Andric 2308*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_EraseFromParent") 2309*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID) 2310*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 2311*0fca6ea1SDimitry Andric } 2312*0fca6ea1SDimitry Andric 2313*0fca6ea1SDimitry Andric bool EraseInstAction::emitActionOpcodesAndDone(MatchTable &Table, 2314*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 2315*0fca6ea1SDimitry Andric if (InsnID != 0) { 2316*0fca6ea1SDimitry Andric emitActionOpcodes(Table, Rule); 2317*0fca6ea1SDimitry Andric return false; 2318*0fca6ea1SDimitry Andric } 2319*0fca6ea1SDimitry Andric 2320*0fca6ea1SDimitry Andric if (!Rule.tryEraseInsnID(0)) 2321*0fca6ea1SDimitry Andric return false; 2322*0fca6ea1SDimitry Andric 2323*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_EraseRootFromParent_Done", -1) 2324*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 2325*0fca6ea1SDimitry Andric return true; 2326*0fca6ea1SDimitry Andric } 2327*0fca6ea1SDimitry Andric 2328*0fca6ea1SDimitry Andric //===- ReplaceRegAction ---------------------------------------------------===// 2329*0fca6ea1SDimitry Andric 2330*0fca6ea1SDimitry Andric void ReplaceRegAction::emitAdditionalPredicates(MatchTable &Table, 2331*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 2332*0fca6ea1SDimitry Andric if (TempRegID != (unsigned)-1) 2333*0fca6ea1SDimitry Andric return; 2334*0fca6ea1SDimitry Andric 2335*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckCanReplaceReg") 2336*0fca6ea1SDimitry Andric << MatchTable::Comment("OldInsnID") 2337*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OldInsnID) 2338*0fca6ea1SDimitry Andric << MatchTable::Comment("OldOpIdx") << MatchTable::ULEB128Value(OldOpIdx) 2339*0fca6ea1SDimitry Andric << MatchTable::Comment("NewInsnId") 2340*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(NewInsnId) 2341*0fca6ea1SDimitry Andric << MatchTable::Comment("NewOpIdx") << MatchTable::ULEB128Value(NewOpIdx) 2342*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 2343*0fca6ea1SDimitry Andric } 2344*0fca6ea1SDimitry Andric 2345*0fca6ea1SDimitry Andric void ReplaceRegAction::emitActionOpcodes(MatchTable &Table, 2346*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 2347*0fca6ea1SDimitry Andric if (TempRegID != (unsigned)-1) { 2348*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_ReplaceRegWithTempReg") 2349*0fca6ea1SDimitry Andric << MatchTable::Comment("OldInsnID") 2350*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OldInsnID) 2351*0fca6ea1SDimitry Andric << MatchTable::Comment("OldOpIdx") 2352*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OldOpIdx) 2353*0fca6ea1SDimitry Andric << MatchTable::Comment("TempRegID") 2354*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(TempRegID) << MatchTable::LineBreak; 2355*0fca6ea1SDimitry Andric } else { 2356*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_ReplaceReg") 2357*0fca6ea1SDimitry Andric << MatchTable::Comment("OldInsnID") 2358*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OldInsnID) 2359*0fca6ea1SDimitry Andric << MatchTable::Comment("OldOpIdx") 2360*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(OldOpIdx) 2361*0fca6ea1SDimitry Andric << MatchTable::Comment("NewInsnId") 2362*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(NewInsnId) 2363*0fca6ea1SDimitry Andric << MatchTable::Comment("NewOpIdx") 2364*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(NewOpIdx) << MatchTable::LineBreak; 2365*0fca6ea1SDimitry Andric } 2366*0fca6ea1SDimitry Andric } 2367*0fca6ea1SDimitry Andric 2368*0fca6ea1SDimitry Andric //===- ConstrainOperandToRegClassAction -----------------------------------===// 2369*0fca6ea1SDimitry Andric 2370*0fca6ea1SDimitry Andric void ConstrainOperandToRegClassAction::emitActionOpcodes( 2371*0fca6ea1SDimitry Andric MatchTable &Table, RuleMatcher &Rule) const { 2372*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_ConstrainOperandRC") 2373*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID) 2374*0fca6ea1SDimitry Andric << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx) 2375*0fca6ea1SDimitry Andric << MatchTable::NamedValue(2, RC.getQualifiedIdName()) 2376*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 2377*0fca6ea1SDimitry Andric } 2378*0fca6ea1SDimitry Andric 2379*0fca6ea1SDimitry Andric //===- MakeTempRegisterAction ---------------------------------------------===// 2380*0fca6ea1SDimitry Andric 2381*0fca6ea1SDimitry Andric void MakeTempRegisterAction::emitActionOpcodes(MatchTable &Table, 2382*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 2383*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_MakeTempReg") 2384*0fca6ea1SDimitry Andric << MatchTable::Comment("TempRegID") 2385*0fca6ea1SDimitry Andric << MatchTable::ULEB128Value(TempRegID) << MatchTable::Comment("TypeID") 2386*0fca6ea1SDimitry Andric << Ty << MatchTable::LineBreak; 2387*0fca6ea1SDimitry Andric } 2388*0fca6ea1SDimitry Andric 2389*0fca6ea1SDimitry Andric } // namespace gi 2390*0fca6ea1SDimitry Andric } // namespace llvm 2391