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