1 //===- Patterns.h ----------------------------------------------*- C++ -*-===// 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 /// \file Contains the Pattern hierarchy alongside helper classes such as 10 /// PatFrag, MIFlagsInfo, PatternType, etc. 11 /// 12 /// These classes are used by the GlobalISel Combiner backend to help parse, 13 /// process and emit MIR patterns. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #ifndef LLVM_UTILS_GLOBALISEL_PATTERNS_H 18 #define LLVM_UTILS_GLOBALISEL_PATTERNS_H 19 20 #include "llvm/ADT/ArrayRef.h" 21 #include "llvm/ADT/SetVector.h" 22 #include "llvm/ADT/SmallVector.h" 23 #include "llvm/ADT/StringMap.h" 24 #include "llvm/ADT/StringRef.h" 25 #include "llvm/ADT/Twine.h" 26 #include <memory> 27 #include <optional> 28 #include <string> 29 30 namespace llvm { 31 32 class Record; 33 class SMLoc; 34 class StringInit; 35 class CodeExpansions; 36 class CodeGenInstruction; 37 struct CodeGenIntrinsic; 38 39 namespace gi { 40 41 class CXXPredicateCode; 42 class LLTCodeGen; 43 class LLTCodeGenOrTempType; 44 class RuleMatcher; 45 46 //===- PatternType --------------------------------------------------------===// 47 48 /// Represent the type of a Pattern Operand. 49 /// 50 /// Types have two form: 51 /// - LLTs, which are straightforward. 52 /// - Special types, e.g. GITypeOf 53 class PatternType { 54 public: 55 static constexpr StringLiteral SpecialTyClassName = "GISpecialType"; 56 static constexpr StringLiteral TypeOfClassName = "GITypeOf"; 57 58 enum PTKind : uint8_t { 59 PT_None, 60 61 PT_ValueType, 62 PT_TypeOf, 63 }; 64 65 PatternType() : Kind(PT_None), Data() {} 66 67 static std::optional<PatternType> get(ArrayRef<SMLoc> DiagLoc, 68 const Record *R, Twine DiagCtx); 69 static PatternType getTypeOf(StringRef OpName); 70 71 bool isNone() const { return Kind == PT_None; } 72 bool isLLT() const { return Kind == PT_ValueType; } 73 bool isSpecial() const { return isTypeOf(); } 74 bool isTypeOf() const { return Kind == PT_TypeOf; } 75 76 StringRef getTypeOfOpName() const; 77 const Record *getLLTRecord() const; 78 79 explicit operator bool() const { return !isNone(); } 80 81 bool operator==(const PatternType &Other) const; 82 bool operator!=(const PatternType &Other) const { return !operator==(Other); } 83 84 std::string str() const; 85 86 private: 87 PatternType(PTKind Kind) : Kind(Kind), Data() {} 88 89 PTKind Kind; 90 union DataT { 91 DataT() : Str() {} 92 93 /// PT_ValueType -> ValueType Def. 94 const Record *Def; 95 96 /// PT_TypeOf -> Operand name (without the '$') 97 StringRef Str; 98 } Data; 99 }; 100 101 //===- Pattern Base Class -------------------------------------------------===// 102 103 /// Base class for all patterns that can be written in an `apply`, `match` or 104 /// `pattern` DAG operator. 105 /// 106 /// For example: 107 /// 108 /// (apply (G_ZEXT $x, $y), (G_ZEXT $y, $z), "return isFoo(${z})") 109 /// 110 /// Creates 3 Pattern objects: 111 /// - Two CodeGenInstruction Patterns 112 /// - A CXXPattern 113 class Pattern { 114 public: 115 enum { 116 K_AnyOpcode, 117 K_CXX, 118 119 K_CodeGenInstruction, 120 K_PatFrag, 121 K_Builtin, 122 }; 123 124 virtual ~Pattern() = default; 125 126 unsigned getKind() const { return Kind; } 127 const char *getKindName() const; 128 129 bool hasName() const { return !Name.empty(); } 130 StringRef getName() const { return Name; } 131 132 virtual void print(raw_ostream &OS, bool PrintName = true) const = 0; 133 void dump() const; 134 135 protected: 136 Pattern(unsigned Kind, StringRef Name) : Kind(Kind), Name(Name) { 137 assert(!Name.empty() && "unnamed pattern!"); 138 } 139 140 void printImpl(raw_ostream &OS, bool PrintName, 141 function_ref<void()> ContentPrinter) const; 142 143 private: 144 unsigned Kind; 145 StringRef Name; 146 }; 147 148 //===- AnyOpcodePattern ---------------------------------------------------===// 149 150 /// `wip_match_opcode` patterns. 151 /// This matches one or more opcodes, and does not check any operands 152 /// whatsoever. 153 /// 154 /// TODO: Long-term, this needs to be removed. It's a hack around MIR 155 /// pattern matching limitations. 156 class AnyOpcodePattern : public Pattern { 157 public: 158 AnyOpcodePattern(StringRef Name) : Pattern(K_AnyOpcode, Name) {} 159 160 static bool classof(const Pattern *P) { return P->getKind() == K_AnyOpcode; } 161 162 void addOpcode(const CodeGenInstruction *I) { Insts.push_back(I); } 163 const auto &insts() const { return Insts; } 164 165 void print(raw_ostream &OS, bool PrintName = true) const override; 166 167 private: 168 SmallVector<const CodeGenInstruction *, 4> Insts; 169 }; 170 171 //===- CXXPattern ---------------------------------------------------------===// 172 173 /// Represents raw C++ code which may need some expansions. 174 /// 175 /// e.g. [{ return isFooBux(${src}.getReg()); }] 176 /// 177 /// For the expanded code, \see CXXPredicateCode. CXXPredicateCode objects are 178 /// created through `expandCode`. 179 /// 180 /// \see CodeExpander and \see CodeExpansions for more information on code 181 /// expansions. 182 /// 183 /// This object has two purposes: 184 /// - Represent C++ code as a pattern entry. 185 /// - Be a factory for expanded C++ code. 186 /// - It's immutable and only holds the raw code so we can expand the same 187 /// CXX pattern multiple times if we need to. 188 /// 189 /// Note that the code is always trimmed in the constructor, so leading and 190 /// trailing whitespaces are removed. This removes bloat in the output, avoids 191 /// formatting issues, but also allows us to check things like 192 /// `.startswith("return")` trivially without worrying about spaces. 193 class CXXPattern : public Pattern { 194 public: 195 CXXPattern(const StringInit &Code, StringRef Name); 196 197 CXXPattern(StringRef Code, StringRef Name) 198 : Pattern(K_CXX, Name), RawCode(Code.trim().str()) {} 199 200 static bool classof(const Pattern *P) { return P->getKind() == K_CXX; } 201 202 void setIsApply(bool Value = true) { IsApply = Value; } 203 StringRef getRawCode() const { return RawCode; } 204 205 /// Expands raw code, replacing things such as `${foo}` with their 206 /// substitution in \p CE. 207 /// 208 /// Can only be used on 'match' CXX Patterns. 'apply' CXX pattern emission 209 /// is handled differently as we emit both the 'match' and 'apply' part 210 /// together in a single Custom CXX Action. 211 /// 212 /// \param CE Map of Code Expansions 213 /// \param Locs SMLocs for the Code Expander, in case it needs to emit 214 /// diagnostics. 215 /// \param AddComment Optionally called to emit a comment before the expanded 216 /// code. 217 /// 218 /// \return A CXXPredicateCode object that contains the expanded code. Note 219 /// that this may or may not insert a new object. All CXXPredicateCode objects 220 /// are held in a set to avoid emitting duplicate C++ code. 221 const CXXPredicateCode & 222 expandCode(const CodeExpansions &CE, ArrayRef<SMLoc> Locs, 223 function_ref<void(raw_ostream &)> AddComment = {}) const; 224 225 void print(raw_ostream &OS, bool PrintName = true) const override; 226 227 private: 228 bool IsApply = false; 229 std::string RawCode; 230 }; 231 232 //===- InstructionPattern ---------------------------------------------===// 233 234 /// An operand for an InstructionPattern. 235 /// 236 /// Operands are composed of three elements: 237 /// - (Optional) Value 238 /// - (Optional) Name 239 /// - (Optional) Type 240 /// 241 /// Some examples: 242 /// (i32 0):$x -> V=int(0), Name='x', Type=i32 243 /// 0:$x -> V=int(0), Name='x' 244 /// $x -> Name='x' 245 /// i32:$x -> Name='x', Type = i32 246 class InstructionOperand { 247 public: 248 using IntImmTy = int64_t; 249 250 InstructionOperand(IntImmTy Imm, StringRef Name, PatternType Type) 251 : Value(Imm), Name(Name), Type(Type) {} 252 253 InstructionOperand(StringRef Name, PatternType Type) 254 : Name(Name), Type(Type) {} 255 256 bool isNamedImmediate() const { return hasImmValue() && isNamedOperand(); } 257 258 bool hasImmValue() const { return Value.has_value(); } 259 IntImmTy getImmValue() const { return *Value; } 260 261 bool isNamedOperand() const { return !Name.empty(); } 262 StringRef getOperandName() const { 263 assert(isNamedOperand() && "Operand is unnamed"); 264 return Name; 265 } 266 267 InstructionOperand withNewName(StringRef NewName) const { 268 InstructionOperand Result = *this; 269 Result.Name = NewName; 270 return Result; 271 } 272 273 void setIsDef(bool Value = true) { Def = Value; } 274 bool isDef() const { return Def; } 275 276 void setType(PatternType NewType) { 277 assert((!Type || (Type == NewType)) && "Overwriting type!"); 278 Type = NewType; 279 } 280 PatternType getType() const { return Type; } 281 282 std::string describe() const; 283 void print(raw_ostream &OS) const; 284 285 void dump() const; 286 287 private: 288 std::optional<int64_t> Value; 289 StringRef Name; 290 PatternType Type; 291 bool Def = false; 292 }; 293 294 /// Base class for CodeGenInstructionPattern & PatFragPattern, which handles all 295 /// the boilerplate for patterns that have a list of operands for some (pseudo) 296 /// instruction. 297 class InstructionPattern : public Pattern { 298 public: 299 virtual ~InstructionPattern() = default; 300 301 static bool classof(const Pattern *P) { 302 return P->getKind() == K_CodeGenInstruction || P->getKind() == K_PatFrag || 303 P->getKind() == K_Builtin; 304 } 305 306 template <typename... Ty> void addOperand(Ty &&...Init) { 307 Operands.emplace_back(std::forward<Ty>(Init)...); 308 } 309 310 auto &operands() { return Operands; } 311 const auto &operands() const { return Operands; } 312 unsigned operands_size() const { return Operands.size(); } 313 InstructionOperand &getOperand(unsigned K) { return Operands[K]; } 314 const InstructionOperand &getOperand(unsigned K) const { return Operands[K]; } 315 316 /// When this InstructionPattern is used as the match root, returns the 317 /// operands that must be redefined in the 'apply' pattern for the rule to be 318 /// valid. 319 /// 320 /// For most patterns, this just returns the defs. 321 /// For PatFrag this only returns the root of the PF. 322 /// 323 /// Returns an empty array on error. 324 virtual ArrayRef<InstructionOperand> getApplyDefsNeeded() const { 325 return {operands().begin(), getNumInstDefs()}; 326 } 327 328 auto named_operands() { 329 return make_filter_range(Operands, 330 [&](auto &O) { return O.isNamedOperand(); }); 331 } 332 333 auto named_operands() const { 334 return make_filter_range(Operands, 335 [&](auto &O) { return O.isNamedOperand(); }); 336 } 337 338 virtual bool isVariadic() const { return false; } 339 virtual unsigned getNumInstOperands() const = 0; 340 virtual unsigned getNumInstDefs() const = 0; 341 342 bool hasAllDefs() const { return operands_size() >= getNumInstDefs(); } 343 344 virtual StringRef getInstName() const = 0; 345 346 /// Diagnoses all uses of special types in this Pattern and returns true if at 347 /// least one diagnostic was emitted. 348 bool diagnoseAllSpecialTypes(ArrayRef<SMLoc> Loc, Twine Msg) const; 349 350 void reportUnreachable(ArrayRef<SMLoc> Locs) const; 351 virtual bool checkSemantics(ArrayRef<SMLoc> Loc); 352 353 void print(raw_ostream &OS, bool PrintName = true) const override; 354 355 protected: 356 InstructionPattern(unsigned K, StringRef Name) : Pattern(K, Name) {} 357 358 virtual void printExtras(raw_ostream &OS) const {} 359 360 SmallVector<InstructionOperand, 4> Operands; 361 }; 362 363 //===- OperandTable -------------------------------------------------------===// 364 365 /// Maps InstructionPattern operands to their definitions. This allows us to tie 366 /// different patterns of a (apply), (match) or (patterns) set of patterns 367 /// together. 368 class OperandTable { 369 public: 370 bool addPattern(InstructionPattern *P, 371 function_ref<void(StringRef)> DiagnoseRedef); 372 373 struct LookupResult { 374 LookupResult() = default; 375 LookupResult(InstructionPattern *Def) : Found(true), Def(Def) {} 376 377 bool Found = false; 378 InstructionPattern *Def = nullptr; 379 380 bool isLiveIn() const { return Found && !Def; } 381 }; 382 383 LookupResult lookup(StringRef OpName) const { 384 if (auto It = Table.find(OpName); It != Table.end()) 385 return LookupResult(It->second); 386 return LookupResult(); 387 } 388 389 InstructionPattern *getDef(StringRef OpName) const { 390 return lookup(OpName).Def; 391 } 392 393 void print(raw_ostream &OS, StringRef Name = "", StringRef Indent = "") const; 394 395 auto begin() const { return Table.begin(); } 396 auto end() const { return Table.end(); } 397 398 void dump() const; 399 400 private: 401 StringMap<InstructionPattern *> Table; 402 }; 403 404 //===- MIFlagsInfo --------------------------------------------------------===// 405 406 /// Helper class to contain data associated with a MIFlags operand. 407 class MIFlagsInfo { 408 public: 409 void addSetFlag(const Record *R); 410 void addUnsetFlag(const Record *R); 411 void addCopyFlag(StringRef InstName); 412 413 const auto &set_flags() const { return SetF; } 414 const auto &unset_flags() const { return UnsetF; } 415 const auto ©_flags() const { return CopyF; } 416 417 private: 418 SetVector<StringRef> SetF, UnsetF, CopyF; 419 }; 420 421 //===- CodeGenInstructionPattern ------------------------------------------===// 422 423 /// Matches an instruction or intrinsic: 424 /// e.g. `G_ADD $x, $y, $z` or `int_amdgcn_cos $a` 425 /// 426 /// Intrinsics are just normal instructions with a special operand for intrinsic 427 /// ID. Despite G_INTRINSIC opcodes being variadic, we consider that the 428 /// Intrinsic's info takes priority. This means we return: 429 /// - false for isVariadic() and other variadic-related queries. 430 /// - getNumInstDefs and getNumInstOperands use the intrinsic's in/out 431 /// operands. 432 class CodeGenInstructionPattern : public InstructionPattern { 433 public: 434 CodeGenInstructionPattern(const CodeGenInstruction &I, StringRef Name) 435 : InstructionPattern(K_CodeGenInstruction, Name), I(I) {} 436 437 static bool classof(const Pattern *P) { 438 return P->getKind() == K_CodeGenInstruction; 439 } 440 441 bool is(StringRef OpcodeName) const; 442 443 void setIntrinsic(const CodeGenIntrinsic *I) { IntrinInfo = I; } 444 const CodeGenIntrinsic *getIntrinsic() const { return IntrinInfo; } 445 bool isIntrinsic() const { return IntrinInfo; } 446 447 bool hasVariadicDefs() const; 448 bool isVariadic() const override; 449 unsigned getNumInstDefs() const override; 450 unsigned getNumInstOperands() const override; 451 452 MIFlagsInfo &getOrCreateMIFlagsInfo(); 453 const MIFlagsInfo *getMIFlagsInfo() const { return FI.get(); } 454 455 const CodeGenInstruction &getInst() const { return I; } 456 StringRef getInstName() const override; 457 458 private: 459 void printExtras(raw_ostream &OS) const override; 460 461 const CodeGenInstruction &I; 462 const CodeGenIntrinsic *IntrinInfo = nullptr; 463 std::unique_ptr<MIFlagsInfo> FI; 464 }; 465 466 //===- OperandTypeChecker -------------------------------------------------===// 467 468 /// This is a trivial type checker for all operands in a set of 469 /// InstructionPatterns. 470 /// 471 /// It infers the type of each operand, check it's consistent with the known 472 /// type of the operand, and then sets all of the types in all operands in 473 /// propagateTypes. 474 /// 475 /// It also handles verifying correctness of special types. 476 class OperandTypeChecker { 477 public: 478 OperandTypeChecker(ArrayRef<SMLoc> DiagLoc) : DiagLoc(DiagLoc) {} 479 480 /// Step 1: Check each pattern one by one. All patterns that pass through here 481 /// are added to a common worklist so propagateTypes can access them. 482 bool check(InstructionPattern &P, 483 std::function<bool(const PatternType &)> VerifyTypeOfOperand); 484 485 /// Step 2: Propagate all types. e.g. if one use of "$a" has type i32, make 486 /// all uses of "$a" have type i32. 487 void propagateTypes(); 488 489 protected: 490 ArrayRef<SMLoc> DiagLoc; 491 492 private: 493 using InconsistentTypeDiagFn = std::function<void()>; 494 495 void PrintSeenWithTypeIn(InstructionPattern &P, StringRef OpName, 496 PatternType Ty) const; 497 498 struct OpTypeInfo { 499 PatternType Type; 500 InconsistentTypeDiagFn PrintTypeSrcNote = []() {}; 501 }; 502 503 StringMap<OpTypeInfo> Types; 504 505 SmallVector<InstructionPattern *, 16> Pats; 506 }; 507 508 //===- PatFrag ------------------------------------------------------------===// 509 510 /// Represents a parsed GICombinePatFrag. This can be thought of as the 511 /// equivalent of a CodeGenInstruction, but for PatFragPatterns. 512 /// 513 /// PatFrags are made of 3 things: 514 /// - Out parameters (defs) 515 /// - In parameters 516 /// - A set of pattern lists (alternatives). 517 /// 518 /// If the PatFrag uses instruction patterns, the root must be one of the defs. 519 /// 520 /// Note that this DOES NOT represent the use of the PatFrag, only its 521 /// definition. The use of the PatFrag in a Pattern is represented by 522 /// PatFragPattern. 523 /// 524 /// PatFrags use the term "parameter" instead of operand because they're 525 /// essentially macros, and using that name avoids confusion. Other than that, 526 /// they're structured similarly to a MachineInstruction - all parameters 527 /// (operands) are in the same list, with defs at the start. This helps mapping 528 /// parameters to values, because, param N of a PatFrag is always operand N of a 529 /// PatFragPattern. 530 class PatFrag { 531 public: 532 static constexpr StringLiteral ClassName = "GICombinePatFrag"; 533 534 enum ParamKind { 535 PK_Root, 536 PK_MachineOperand, 537 PK_Imm, 538 }; 539 540 struct Param { 541 StringRef Name; 542 ParamKind Kind; 543 }; 544 545 using ParamVec = SmallVector<Param, 4>; 546 using ParamIt = ParamVec::const_iterator; 547 548 /// Represents an alternative of the PatFrag. When parsing a GICombinePatFrag, 549 /// this is created from its "Alternatives" list. Each alternative is a list 550 /// of patterns written wrapped in a `(pattern ...)` dag init. 551 /// 552 /// Each argument to the `pattern` DAG operator is parsed into a Pattern 553 /// instance. 554 struct Alternative { 555 OperandTable OpTable; 556 SmallVector<std::unique_ptr<Pattern>, 4> Pats; 557 }; 558 559 explicit PatFrag(const Record &Def); 560 561 static StringRef getParamKindStr(ParamKind OK); 562 563 StringRef getName() const; 564 565 const Record &getDef() const { return Def; } 566 ArrayRef<SMLoc> getLoc() const; 567 568 Alternative &addAlternative() { return Alts.emplace_back(); } 569 const Alternative &getAlternative(unsigned K) const { return Alts[K]; } 570 unsigned num_alternatives() const { return Alts.size(); } 571 572 void addInParam(StringRef Name, ParamKind Kind); 573 iterator_range<ParamIt> in_params() const; 574 unsigned num_in_params() const { return Params.size() - NumOutParams; } 575 576 void addOutParam(StringRef Name, ParamKind Kind); 577 iterator_range<ParamIt> out_params() const; 578 unsigned num_out_params() const { return NumOutParams; } 579 580 unsigned num_roots() const; 581 unsigned num_params() const { return num_in_params() + num_out_params(); } 582 583 /// Finds the operand \p Name and returns its index or -1 if not found. 584 /// Remember that all params are part of the same list, with out params at the 585 /// start. This means that the index returned can be used to access operands 586 /// of InstructionPatterns. 587 unsigned getParamIdx(StringRef Name) const; 588 const Param &getParam(unsigned K) const { return Params[K]; } 589 590 bool canBeMatchRoot() const { return num_roots() == 1; } 591 592 void print(raw_ostream &OS, StringRef Indent = "") const; 593 void dump() const; 594 595 /// Checks if the in-param \p ParamName can be unbound or not. 596 /// \p ArgName is the name of the argument passed to the PatFrag. 597 /// 598 /// An argument can be unbound only if, for all alternatives: 599 /// - There is no CXX pattern, OR: 600 /// - There is an InstructionPattern that binds the parameter. 601 /// 602 /// e.g. in (MyPatFrag $foo), if $foo has never been seen before (= it's 603 /// unbound), this checks if MyPatFrag supports it or not. 604 bool handleUnboundInParam(StringRef ParamName, StringRef ArgName, 605 ArrayRef<SMLoc> DiagLoc) const; 606 607 bool checkSemantics(); 608 bool buildOperandsTables(); 609 610 private: 611 static void printParamsList(raw_ostream &OS, iterator_range<ParamIt> Params); 612 613 void PrintError(Twine Msg) const; 614 615 const Record &Def; 616 unsigned NumOutParams = 0; 617 ParamVec Params; 618 SmallVector<Alternative, 2> Alts; 619 }; 620 621 //===- PatFragPattern -----------------------------------------------------===// 622 623 /// Represents a use of a GICombinePatFrag. 624 class PatFragPattern : public InstructionPattern { 625 public: 626 PatFragPattern(const PatFrag &PF, StringRef Name) 627 : InstructionPattern(K_PatFrag, Name), PF(PF) {} 628 629 static bool classof(const Pattern *P) { return P->getKind() == K_PatFrag; } 630 631 const PatFrag &getPatFrag() const { return PF; } 632 StringRef getInstName() const override { return PF.getName(); } 633 634 unsigned getNumInstDefs() const override { return PF.num_out_params(); } 635 unsigned getNumInstOperands() const override { return PF.num_params(); } 636 637 ArrayRef<InstructionOperand> getApplyDefsNeeded() const override; 638 639 bool checkSemantics(ArrayRef<SMLoc> DiagLoc) override; 640 641 /// Before emitting the patterns inside the PatFrag, add all necessary code 642 /// expansions to \p PatFragCEs imported from \p ParentCEs. 643 /// 644 /// For a MachineOperand PatFrag parameter, this will fetch the expansion for 645 /// that operand from \p ParentCEs and add it to \p PatFragCEs. Errors can be 646 /// emitted if the MachineOperand reference is unbound. 647 /// 648 /// For an Immediate PatFrag parameter this simply adds the integer value to 649 /// \p PatFragCEs as an expansion. 650 /// 651 /// \param ParentCEs Contains all of the code expansions declared by the other 652 /// patterns emitted so far in the pattern list containing 653 /// this PatFragPattern. 654 /// \param PatFragCEs Output Code Expansions (usually empty) 655 /// \param DiagLoc Diagnostic loc in case an error occurs. 656 /// \return `true` on success, `false` on failure. 657 bool mapInputCodeExpansions(const CodeExpansions &ParentCEs, 658 CodeExpansions &PatFragCEs, 659 ArrayRef<SMLoc> DiagLoc) const; 660 661 private: 662 const PatFrag &PF; 663 }; 664 665 //===- BuiltinPattern -----------------------------------------------------===// 666 667 /// Represents builtin instructions such as "GIReplaceReg" and "GIEraseRoot". 668 enum BuiltinKind { 669 BI_ReplaceReg, 670 BI_EraseRoot, 671 }; 672 673 class BuiltinPattern : public InstructionPattern { 674 struct BuiltinInfo { 675 StringLiteral DefName; 676 BuiltinKind Kind; 677 unsigned NumOps; 678 unsigned NumDefs; 679 }; 680 681 static constexpr std::array<BuiltinInfo, 2> KnownBuiltins = {{ 682 {"GIReplaceReg", BI_ReplaceReg, 2, 1}, 683 {"GIEraseRoot", BI_EraseRoot, 0, 0}, 684 }}; 685 686 public: 687 static constexpr StringLiteral ClassName = "GIBuiltinInst"; 688 689 BuiltinPattern(const Record &Def, StringRef Name) 690 : InstructionPattern(K_Builtin, Name), I(getBuiltinInfo(Def)) {} 691 692 static bool classof(const Pattern *P) { return P->getKind() == K_Builtin; } 693 694 unsigned getNumInstOperands() const override { return I.NumOps; } 695 unsigned getNumInstDefs() const override { return I.NumDefs; } 696 StringRef getInstName() const override { return I.DefName; } 697 BuiltinKind getBuiltinKind() const { return I.Kind; } 698 699 bool checkSemantics(ArrayRef<SMLoc> Loc) override; 700 701 private: 702 static BuiltinInfo getBuiltinInfo(const Record &Def); 703 704 BuiltinInfo I; 705 }; 706 707 } // namespace gi 708 } // end namespace llvm 709 710 #endif // ifndef LLVM_UTILS_GLOBALISEL_PATTERNS_H 711