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