brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.2 KiB · 2bf2a22 Raw
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 &copy_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