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