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