xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/Common/GlobalISel/Patterns.h (revision 5036d9652a5701d00e9e40ea942c278e9f77d33d)
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 &copy_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