xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===- GlobalISelMatchTable.h ---------------------------------------------===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric //
9*0fca6ea1SDimitry Andric /// \file
10*0fca6ea1SDimitry Andric /// This file contains the code related to the GlobalISel Match Table emitted by
11*0fca6ea1SDimitry Andric /// GlobalISelEmitter.cpp. The generated match table is interpreted at runtime
12*0fca6ea1SDimitry Andric /// by `GIMatchTableExecutorImpl.h` to match & apply ISel patterns.
13*0fca6ea1SDimitry Andric ///
14*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
15*0fca6ea1SDimitry Andric 
16*0fca6ea1SDimitry Andric #ifndef LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLE_H
17*0fca6ea1SDimitry Andric #define LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLE_H
18*0fca6ea1SDimitry Andric 
19*0fca6ea1SDimitry Andric #include "Common/CodeGenDAGPatterns.h"
20*0fca6ea1SDimitry Andric #include "llvm/ADT/ArrayRef.h"
21*0fca6ea1SDimitry Andric #include "llvm/ADT/DenseMap.h"
22*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
23*0fca6ea1SDimitry Andric #include "llvm/ADT/StringMap.h"
24*0fca6ea1SDimitry Andric #include "llvm/ADT/StringRef.h"
25*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/LowLevelType.h"
26*0fca6ea1SDimitry Andric #include "llvm/Support/Error.h"
27*0fca6ea1SDimitry Andric #include "llvm/Support/SaveAndRestore.h"
28*0fca6ea1SDimitry Andric #include <deque>
29*0fca6ea1SDimitry Andric #include <list>
30*0fca6ea1SDimitry Andric #include <map>
31*0fca6ea1SDimitry Andric #include <memory>
32*0fca6ea1SDimitry Andric #include <optional>
33*0fca6ea1SDimitry Andric #include <set>
34*0fca6ea1SDimitry Andric #include <string>
35*0fca6ea1SDimitry Andric #include <vector>
36*0fca6ea1SDimitry Andric 
37*0fca6ea1SDimitry Andric namespace llvm {
38*0fca6ea1SDimitry Andric 
39*0fca6ea1SDimitry Andric class raw_ostream;
40*0fca6ea1SDimitry Andric class Record;
41*0fca6ea1SDimitry Andric class SMLoc;
42*0fca6ea1SDimitry Andric class CodeGenRegisterClass;
43*0fca6ea1SDimitry Andric 
44*0fca6ea1SDimitry Andric // Use a namespace to avoid conflicts because there's some fairly generic names
45*0fca6ea1SDimitry Andric // in there (e.g. Matcher).
46*0fca6ea1SDimitry Andric namespace gi {
47*0fca6ea1SDimitry Andric class MatchTable;
48*0fca6ea1SDimitry Andric class Matcher;
49*0fca6ea1SDimitry Andric class OperandMatcher;
50*0fca6ea1SDimitry Andric class MatchAction;
51*0fca6ea1SDimitry Andric class PredicateMatcher;
52*0fca6ea1SDimitry Andric class InstructionMatcher;
53*0fca6ea1SDimitry Andric 
54*0fca6ea1SDimitry Andric enum {
55*0fca6ea1SDimitry Andric   GISF_IgnoreCopies = 0x1,
56*0fca6ea1SDimitry Andric };
57*0fca6ea1SDimitry Andric 
58*0fca6ea1SDimitry Andric using GISelFlags = std::uint16_t;
59*0fca6ea1SDimitry Andric 
60*0fca6ea1SDimitry Andric //===- Helper functions ---------------------------------------------------===//
61*0fca6ea1SDimitry Andric 
62*0fca6ea1SDimitry Andric void emitEncodingMacrosDef(raw_ostream &OS);
63*0fca6ea1SDimitry Andric void emitEncodingMacrosUndef(raw_ostream &OS);
64*0fca6ea1SDimitry Andric 
65*0fca6ea1SDimitry Andric std::string getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset,
66*0fca6ea1SDimitry Andric                                     int HwModeIdx);
67*0fca6ea1SDimitry Andric 
68*0fca6ea1SDimitry Andric /// Takes a sequence of \p Rules and group them based on the predicates
69*0fca6ea1SDimitry Andric /// they share. \p MatcherStorage is used as a memory container
70*0fca6ea1SDimitry Andric /// for the group that are created as part of this process.
71*0fca6ea1SDimitry Andric ///
72*0fca6ea1SDimitry Andric /// What this optimization does looks like if GroupT = GroupMatcher:
73*0fca6ea1SDimitry Andric /// Output without optimization:
74*0fca6ea1SDimitry Andric /// \verbatim
75*0fca6ea1SDimitry Andric /// # R1
76*0fca6ea1SDimitry Andric ///  # predicate A
77*0fca6ea1SDimitry Andric ///  # predicate B
78*0fca6ea1SDimitry Andric ///  ...
79*0fca6ea1SDimitry Andric /// # R2
80*0fca6ea1SDimitry Andric ///  # predicate A // <-- effectively this is going to be checked twice.
81*0fca6ea1SDimitry Andric ///                //     Once in R1 and once in R2.
82*0fca6ea1SDimitry Andric ///  # predicate C
83*0fca6ea1SDimitry Andric /// \endverbatim
84*0fca6ea1SDimitry Andric /// Output with optimization:
85*0fca6ea1SDimitry Andric /// \verbatim
86*0fca6ea1SDimitry Andric /// # Group1_2
87*0fca6ea1SDimitry Andric ///  # predicate A // <-- Check is now shared.
88*0fca6ea1SDimitry Andric ///  # R1
89*0fca6ea1SDimitry Andric ///   # predicate B
90*0fca6ea1SDimitry Andric ///  # R2
91*0fca6ea1SDimitry Andric ///   # predicate C
92*0fca6ea1SDimitry Andric /// \endverbatim
93*0fca6ea1SDimitry Andric template <class GroupT>
94*0fca6ea1SDimitry Andric std::vector<Matcher *>
95*0fca6ea1SDimitry Andric optimizeRules(ArrayRef<Matcher *> Rules,
96*0fca6ea1SDimitry Andric               std::vector<std::unique_ptr<Matcher>> &MatcherStorage);
97*0fca6ea1SDimitry Andric 
98*0fca6ea1SDimitry Andric /// A record to be stored in a MatchTable.
99*0fca6ea1SDimitry Andric ///
100*0fca6ea1SDimitry Andric /// This class represents any and all output that may be required to emit the
101*0fca6ea1SDimitry Andric /// MatchTable. Instances  are most often configured to represent an opcode or
102*0fca6ea1SDimitry Andric /// value that will be emitted to the table with some formatting but it can also
103*0fca6ea1SDimitry Andric /// represent commas, comments, and other formatting instructions.
104*0fca6ea1SDimitry Andric struct MatchTableRecord {
105*0fca6ea1SDimitry Andric   enum RecordFlagsBits {
106*0fca6ea1SDimitry Andric     MTRF_None = 0x0,
107*0fca6ea1SDimitry Andric     /// Causes EmitStr to be formatted as comment when emitted.
108*0fca6ea1SDimitry Andric     MTRF_Comment = 0x1,
109*0fca6ea1SDimitry Andric     /// Causes the record value to be followed by a comma when emitted.
110*0fca6ea1SDimitry Andric     MTRF_CommaFollows = 0x2,
111*0fca6ea1SDimitry Andric     /// Causes the record value to be followed by a line break when emitted.
112*0fca6ea1SDimitry Andric     MTRF_LineBreakFollows = 0x4,
113*0fca6ea1SDimitry Andric     /// Indicates that the record defines a label and causes an additional
114*0fca6ea1SDimitry Andric     /// comment to be emitted containing the index of the label.
115*0fca6ea1SDimitry Andric     MTRF_Label = 0x8,
116*0fca6ea1SDimitry Andric     /// Causes the record to be emitted as the index of the label specified by
117*0fca6ea1SDimitry Andric     /// LabelID along with a comment indicating where that label is.
118*0fca6ea1SDimitry Andric     MTRF_JumpTarget = 0x10,
119*0fca6ea1SDimitry Andric     /// Causes the formatter to add a level of indentation before emitting the
120*0fca6ea1SDimitry Andric     /// record.
121*0fca6ea1SDimitry Andric     MTRF_Indent = 0x20,
122*0fca6ea1SDimitry Andric     /// Causes the formatter to remove a level of indentation after emitting the
123*0fca6ea1SDimitry Andric     /// record.
124*0fca6ea1SDimitry Andric     MTRF_Outdent = 0x40,
125*0fca6ea1SDimitry Andric     /// Causes the formatter to not use encoding macros to emit this multi-byte
126*0fca6ea1SDimitry Andric     /// value.
127*0fca6ea1SDimitry Andric     MTRF_PreEncoded = 0x80,
128*0fca6ea1SDimitry Andric   };
129*0fca6ea1SDimitry Andric 
130*0fca6ea1SDimitry Andric   /// When MTRF_Label or MTRF_JumpTarget is used, indicates a label id to
131*0fca6ea1SDimitry Andric   /// reference or define.
132*0fca6ea1SDimitry Andric   unsigned LabelID;
133*0fca6ea1SDimitry Andric   /// The string to emit. Depending on the MTRF_* flags it may be a comment, a
134*0fca6ea1SDimitry Andric   /// value, a label name.
135*0fca6ea1SDimitry Andric   std::string EmitStr;
136*0fca6ea1SDimitry Andric 
137*0fca6ea1SDimitry Andric private:
138*0fca6ea1SDimitry Andric   /// The number of MatchTable elements described by this record. Comments are 0
139*0fca6ea1SDimitry Andric   /// while values are typically 1. Values >1 may occur when we need to emit
140*0fca6ea1SDimitry Andric   /// values that exceed the size of a MatchTable element.
141*0fca6ea1SDimitry Andric   unsigned NumElements;
142*0fca6ea1SDimitry Andric 
143*0fca6ea1SDimitry Andric public:
144*0fca6ea1SDimitry Andric   /// A bitfield of RecordFlagsBits flags.
145*0fca6ea1SDimitry Andric   unsigned Flags;
146*0fca6ea1SDimitry Andric 
147*0fca6ea1SDimitry Andric   /// The actual run-time value, if known
148*0fca6ea1SDimitry Andric   int64_t RawValue;
149*0fca6ea1SDimitry Andric 
150*0fca6ea1SDimitry Andric   MatchTableRecord(std::optional<unsigned> LabelID_, StringRef EmitStr,
151*0fca6ea1SDimitry Andric                    unsigned NumElements, unsigned Flags,
152*0fca6ea1SDimitry Andric                    int64_t RawValue = std::numeric_limits<int64_t>::min())
153*0fca6ea1SDimitry Andric       : LabelID(LabelID_.value_or(~0u)), EmitStr(EmitStr),
154*0fca6ea1SDimitry Andric         NumElements(NumElements), Flags(Flags), RawValue(RawValue) {
155*0fca6ea1SDimitry Andric     assert((!LabelID_ || LabelID != ~0u) &&
156*0fca6ea1SDimitry Andric            "This value is reserved for non-labels");
157*0fca6ea1SDimitry Andric   }
158*0fca6ea1SDimitry Andric   MatchTableRecord(const MatchTableRecord &Other) = default;
159*0fca6ea1SDimitry Andric   MatchTableRecord(MatchTableRecord &&Other) = default;
160*0fca6ea1SDimitry Andric 
161*0fca6ea1SDimitry Andric   /// Useful if a Match Table Record gets optimized out
162*0fca6ea1SDimitry Andric   void turnIntoComment() {
163*0fca6ea1SDimitry Andric     Flags |= MTRF_Comment;
164*0fca6ea1SDimitry Andric     Flags &= ~MTRF_CommaFollows;
165*0fca6ea1SDimitry Andric     NumElements = 0;
166*0fca6ea1SDimitry Andric   }
167*0fca6ea1SDimitry Andric 
168*0fca6ea1SDimitry Andric   /// For Jump Table generation purposes
169*0fca6ea1SDimitry Andric   bool operator<(const MatchTableRecord &Other) const {
170*0fca6ea1SDimitry Andric     return RawValue < Other.RawValue;
171*0fca6ea1SDimitry Andric   }
172*0fca6ea1SDimitry Andric   int64_t getRawValue() const { return RawValue; }
173*0fca6ea1SDimitry Andric 
174*0fca6ea1SDimitry Andric   void emit(raw_ostream &OS, bool LineBreakNextAfterThis,
175*0fca6ea1SDimitry Andric             const MatchTable &Table) const;
176*0fca6ea1SDimitry Andric   unsigned size() const { return NumElements; }
177*0fca6ea1SDimitry Andric };
178*0fca6ea1SDimitry Andric 
179*0fca6ea1SDimitry Andric /// Holds the contents of a generated MatchTable to enable formatting and the
180*0fca6ea1SDimitry Andric /// necessary index tracking needed to support GIM_Try.
181*0fca6ea1SDimitry Andric class MatchTable {
182*0fca6ea1SDimitry Andric   /// An unique identifier for the table. The generated table will be named
183*0fca6ea1SDimitry Andric   /// MatchTable${ID}.
184*0fca6ea1SDimitry Andric   unsigned ID;
185*0fca6ea1SDimitry Andric   /// The records that make up the table. Also includes comments describing the
186*0fca6ea1SDimitry Andric   /// values being emitted and line breaks to format it.
187*0fca6ea1SDimitry Andric   std::vector<MatchTableRecord> Contents;
188*0fca6ea1SDimitry Andric   /// The currently defined labels.
189*0fca6ea1SDimitry Andric   DenseMap<unsigned, unsigned> LabelMap;
190*0fca6ea1SDimitry Andric   /// Tracks the sum of MatchTableRecord::NumElements as the table is built.
191*0fca6ea1SDimitry Andric   unsigned CurrentSize = 0;
192*0fca6ea1SDimitry Andric   /// A unique identifier for a MatchTable label.
193*0fca6ea1SDimitry Andric   unsigned CurrentLabelID = 0;
194*0fca6ea1SDimitry Andric   /// Determines if the table should be instrumented for rule coverage tracking.
195*0fca6ea1SDimitry Andric   bool IsWithCoverage;
196*0fca6ea1SDimitry Andric   /// Whether this table is for the GISel combiner.
197*0fca6ea1SDimitry Andric   bool IsCombinerTable;
198*0fca6ea1SDimitry Andric 
199*0fca6ea1SDimitry Andric public:
200*0fca6ea1SDimitry Andric   static MatchTableRecord LineBreak;
201*0fca6ea1SDimitry Andric   static MatchTableRecord Comment(StringRef Comment);
202*0fca6ea1SDimitry Andric   static MatchTableRecord Opcode(StringRef Opcode, int IndentAdjust = 0);
203*0fca6ea1SDimitry Andric   static MatchTableRecord NamedValue(unsigned NumBytes, StringRef NamedValue);
204*0fca6ea1SDimitry Andric   static MatchTableRecord NamedValue(unsigned NumBytes, StringRef NamedValue,
205*0fca6ea1SDimitry Andric                                      int64_t RawValue);
206*0fca6ea1SDimitry Andric   static MatchTableRecord NamedValue(unsigned NumBytes, StringRef Namespace,
207*0fca6ea1SDimitry Andric                                      StringRef NamedValue);
208*0fca6ea1SDimitry Andric   static MatchTableRecord NamedValue(unsigned NumBytes, StringRef Namespace,
209*0fca6ea1SDimitry Andric                                      StringRef NamedValue, int64_t RawValue);
210*0fca6ea1SDimitry Andric   static MatchTableRecord IntValue(unsigned NumBytes, int64_t IntValue);
211*0fca6ea1SDimitry Andric   static MatchTableRecord ULEB128Value(uint64_t IntValue);
212*0fca6ea1SDimitry Andric   static MatchTableRecord Label(unsigned LabelID);
213*0fca6ea1SDimitry Andric   static MatchTableRecord JumpTarget(unsigned LabelID);
214*0fca6ea1SDimitry Andric 
215*0fca6ea1SDimitry Andric   static MatchTable buildTable(ArrayRef<Matcher *> Rules, bool WithCoverage,
216*0fca6ea1SDimitry Andric                                bool IsCombiner = false);
217*0fca6ea1SDimitry Andric 
218*0fca6ea1SDimitry Andric   MatchTable(bool WithCoverage, bool IsCombinerTable, unsigned ID = 0)
219*0fca6ea1SDimitry Andric       : ID(ID), IsWithCoverage(WithCoverage), IsCombinerTable(IsCombinerTable) {
220*0fca6ea1SDimitry Andric   }
221*0fca6ea1SDimitry Andric 
222*0fca6ea1SDimitry Andric   bool isWithCoverage() const { return IsWithCoverage; }
223*0fca6ea1SDimitry Andric   bool isCombiner() const { return IsCombinerTable; }
224*0fca6ea1SDimitry Andric 
225*0fca6ea1SDimitry Andric   void push_back(const MatchTableRecord &Value) {
226*0fca6ea1SDimitry Andric     if (Value.Flags & MatchTableRecord::MTRF_Label)
227*0fca6ea1SDimitry Andric       defineLabel(Value.LabelID);
228*0fca6ea1SDimitry Andric     Contents.push_back(Value);
229*0fca6ea1SDimitry Andric     CurrentSize += Value.size();
230*0fca6ea1SDimitry Andric   }
231*0fca6ea1SDimitry Andric 
232*0fca6ea1SDimitry Andric   unsigned allocateLabelID() { return CurrentLabelID++; }
233*0fca6ea1SDimitry Andric 
234*0fca6ea1SDimitry Andric   void defineLabel(unsigned LabelID) {
235*0fca6ea1SDimitry Andric     LabelMap.insert(std::pair(LabelID, CurrentSize));
236*0fca6ea1SDimitry Andric   }
237*0fca6ea1SDimitry Andric 
238*0fca6ea1SDimitry Andric   unsigned getLabelIndex(unsigned LabelID) const {
239*0fca6ea1SDimitry Andric     const auto I = LabelMap.find(LabelID);
240*0fca6ea1SDimitry Andric     assert(I != LabelMap.end() && "Use of undeclared label");
241*0fca6ea1SDimitry Andric     return I->second;
242*0fca6ea1SDimitry Andric   }
243*0fca6ea1SDimitry Andric 
244*0fca6ea1SDimitry Andric   void emitUse(raw_ostream &OS) const;
245*0fca6ea1SDimitry Andric   void emitDeclaration(raw_ostream &OS) const;
246*0fca6ea1SDimitry Andric };
247*0fca6ea1SDimitry Andric 
248*0fca6ea1SDimitry Andric inline MatchTable &operator<<(MatchTable &Table,
249*0fca6ea1SDimitry Andric                               const MatchTableRecord &Value) {
250*0fca6ea1SDimitry Andric   Table.push_back(Value);
251*0fca6ea1SDimitry Andric   return Table;
252*0fca6ea1SDimitry Andric }
253*0fca6ea1SDimitry Andric 
254*0fca6ea1SDimitry Andric /// This class stands in for LLT wherever we want to tablegen-erate an
255*0fca6ea1SDimitry Andric /// equivalent at compiler run-time.
256*0fca6ea1SDimitry Andric class LLTCodeGen {
257*0fca6ea1SDimitry Andric private:
258*0fca6ea1SDimitry Andric   LLT Ty;
259*0fca6ea1SDimitry Andric 
260*0fca6ea1SDimitry Andric public:
261*0fca6ea1SDimitry Andric   LLTCodeGen() = default;
262*0fca6ea1SDimitry Andric   LLTCodeGen(const LLT &Ty) : Ty(Ty) {}
263*0fca6ea1SDimitry Andric 
264*0fca6ea1SDimitry Andric   std::string getCxxEnumValue() const;
265*0fca6ea1SDimitry Andric 
266*0fca6ea1SDimitry Andric   void emitCxxEnumValue(raw_ostream &OS) const;
267*0fca6ea1SDimitry Andric   void emitCxxConstructorCall(raw_ostream &OS) const;
268*0fca6ea1SDimitry Andric 
269*0fca6ea1SDimitry Andric   const LLT &get() const { return Ty; }
270*0fca6ea1SDimitry Andric 
271*0fca6ea1SDimitry Andric   /// This ordering is used for std::unique() and llvm::sort(). There's no
272*0fca6ea1SDimitry Andric   /// particular logic behind the order but either A < B or B < A must be
273*0fca6ea1SDimitry Andric   /// true if A != B.
274*0fca6ea1SDimitry Andric   bool operator<(const LLTCodeGen &Other) const;
275*0fca6ea1SDimitry Andric   bool operator==(const LLTCodeGen &B) const { return Ty == B.Ty; }
276*0fca6ea1SDimitry Andric };
277*0fca6ea1SDimitry Andric 
278*0fca6ea1SDimitry Andric // Track all types that are used so we can emit the corresponding enum.
279*0fca6ea1SDimitry Andric extern std::set<LLTCodeGen> KnownTypes;
280*0fca6ea1SDimitry Andric 
281*0fca6ea1SDimitry Andric /// Convert an MVT to an equivalent LLT if possible, or the invalid LLT() for
282*0fca6ea1SDimitry Andric /// MVTs that don't map cleanly to an LLT (e.g., iPTR, *any, ...).
283*0fca6ea1SDimitry Andric std::optional<LLTCodeGen> MVTToLLT(MVT::SimpleValueType SVT);
284*0fca6ea1SDimitry Andric 
285*0fca6ea1SDimitry Andric using TempTypeIdx = int64_t;
286*0fca6ea1SDimitry Andric class LLTCodeGenOrTempType {
287*0fca6ea1SDimitry Andric public:
288*0fca6ea1SDimitry Andric   LLTCodeGenOrTempType(const LLTCodeGen &LLT) : Data(LLT) {}
289*0fca6ea1SDimitry Andric   LLTCodeGenOrTempType(TempTypeIdx TempTy) : Data(TempTy) {}
290*0fca6ea1SDimitry Andric 
291*0fca6ea1SDimitry Andric   bool isLLTCodeGen() const { return std::holds_alternative<LLTCodeGen>(Data); }
292*0fca6ea1SDimitry Andric   bool isTempTypeIdx() const {
293*0fca6ea1SDimitry Andric     return std::holds_alternative<TempTypeIdx>(Data);
294*0fca6ea1SDimitry Andric   }
295*0fca6ea1SDimitry Andric 
296*0fca6ea1SDimitry Andric   const LLTCodeGen &getLLTCodeGen() const {
297*0fca6ea1SDimitry Andric     assert(isLLTCodeGen());
298*0fca6ea1SDimitry Andric     return std::get<LLTCodeGen>(Data);
299*0fca6ea1SDimitry Andric   }
300*0fca6ea1SDimitry Andric 
301*0fca6ea1SDimitry Andric   TempTypeIdx getTempTypeIdx() const {
302*0fca6ea1SDimitry Andric     assert(isTempTypeIdx());
303*0fca6ea1SDimitry Andric     return std::get<TempTypeIdx>(Data);
304*0fca6ea1SDimitry Andric   }
305*0fca6ea1SDimitry Andric 
306*0fca6ea1SDimitry Andric private:
307*0fca6ea1SDimitry Andric   std::variant<LLTCodeGen, TempTypeIdx> Data;
308*0fca6ea1SDimitry Andric };
309*0fca6ea1SDimitry Andric 
310*0fca6ea1SDimitry Andric inline MatchTable &operator<<(MatchTable &Table,
311*0fca6ea1SDimitry Andric                               const LLTCodeGenOrTempType &Ty) {
312*0fca6ea1SDimitry Andric   if (Ty.isLLTCodeGen())
313*0fca6ea1SDimitry Andric     Table << MatchTable::NamedValue(1, Ty.getLLTCodeGen().getCxxEnumValue());
314*0fca6ea1SDimitry Andric   else
315*0fca6ea1SDimitry Andric     Table << MatchTable::IntValue(1, Ty.getTempTypeIdx());
316*0fca6ea1SDimitry Andric   return Table;
317*0fca6ea1SDimitry Andric }
318*0fca6ea1SDimitry Andric 
319*0fca6ea1SDimitry Andric //===- Matchers -----------------------------------------------------------===//
320*0fca6ea1SDimitry Andric class Matcher {
321*0fca6ea1SDimitry Andric public:
322*0fca6ea1SDimitry Andric   virtual ~Matcher();
323*0fca6ea1SDimitry Andric   virtual void optimize();
324*0fca6ea1SDimitry Andric   virtual void emit(MatchTable &Table) = 0;
325*0fca6ea1SDimitry Andric 
326*0fca6ea1SDimitry Andric   virtual bool hasFirstCondition() const = 0;
327*0fca6ea1SDimitry Andric   virtual const PredicateMatcher &getFirstCondition() const = 0;
328*0fca6ea1SDimitry Andric   virtual std::unique_ptr<PredicateMatcher> popFirstCondition() = 0;
329*0fca6ea1SDimitry Andric };
330*0fca6ea1SDimitry Andric 
331*0fca6ea1SDimitry Andric class GroupMatcher final : public Matcher {
332*0fca6ea1SDimitry Andric   /// Conditions that form a common prefix of all the matchers contained.
333*0fca6ea1SDimitry Andric   SmallVector<std::unique_ptr<PredicateMatcher>, 1> Conditions;
334*0fca6ea1SDimitry Andric 
335*0fca6ea1SDimitry Andric   /// All the nested matchers, sharing a common prefix.
336*0fca6ea1SDimitry Andric   std::vector<Matcher *> Matchers;
337*0fca6ea1SDimitry Andric 
338*0fca6ea1SDimitry Andric   /// An owning collection for any auxiliary matchers created while optimizing
339*0fca6ea1SDimitry Andric   /// nested matchers contained.
340*0fca6ea1SDimitry Andric   std::vector<std::unique_ptr<Matcher>> MatcherStorage;
341*0fca6ea1SDimitry Andric 
342*0fca6ea1SDimitry Andric public:
343*0fca6ea1SDimitry Andric   /// Add a matcher to the collection of nested matchers if it meets the
344*0fca6ea1SDimitry Andric   /// requirements, and return true. If it doesn't, do nothing and return false.
345*0fca6ea1SDimitry Andric   ///
346*0fca6ea1SDimitry Andric   /// Expected to preserve its argument, so it could be moved out later on.
347*0fca6ea1SDimitry Andric   bool addMatcher(Matcher &Candidate);
348*0fca6ea1SDimitry Andric 
349*0fca6ea1SDimitry Andric   /// Mark the matcher as fully-built and ensure any invariants expected by both
350*0fca6ea1SDimitry Andric   /// optimize() and emit(...) methods. Generally, both sequences of calls
351*0fca6ea1SDimitry Andric   /// are expected to lead to a sensible result:
352*0fca6ea1SDimitry Andric   ///
353*0fca6ea1SDimitry Andric   /// addMatcher(...)*; finalize(); optimize(); emit(...); and
354*0fca6ea1SDimitry Andric   /// addMatcher(...)*; finalize(); emit(...);
355*0fca6ea1SDimitry Andric   ///
356*0fca6ea1SDimitry Andric   /// or generally
357*0fca6ea1SDimitry Andric   ///
358*0fca6ea1SDimitry Andric   /// addMatcher(...)*; finalize(); { optimize()*; emit(...); }*
359*0fca6ea1SDimitry Andric   ///
360*0fca6ea1SDimitry Andric   /// Multiple calls to optimize() are expected to be handled gracefully, though
361*0fca6ea1SDimitry Andric   /// optimize() is not expected to be idempotent. Multiple calls to finalize()
362*0fca6ea1SDimitry Andric   /// aren't generally supported. emit(...) is expected to be non-mutating and
363*0fca6ea1SDimitry Andric   /// producing the exact same results upon repeated calls.
364*0fca6ea1SDimitry Andric   ///
365*0fca6ea1SDimitry Andric   /// addMatcher() calls after the finalize() call are not supported.
366*0fca6ea1SDimitry Andric   ///
367*0fca6ea1SDimitry Andric   /// finalize() and optimize() are both allowed to mutate the contained
368*0fca6ea1SDimitry Andric   /// matchers, so moving them out after finalize() is not supported.
369*0fca6ea1SDimitry Andric   void finalize();
370*0fca6ea1SDimitry Andric   void optimize() override;
371*0fca6ea1SDimitry Andric   void emit(MatchTable &Table) override;
372*0fca6ea1SDimitry Andric 
373*0fca6ea1SDimitry Andric   /// Could be used to move out the matchers added previously, unless finalize()
374*0fca6ea1SDimitry Andric   /// has been already called. If any of the matchers are moved out, the group
375*0fca6ea1SDimitry Andric   /// becomes safe to destroy, but not safe to re-use for anything else.
376*0fca6ea1SDimitry Andric   iterator_range<std::vector<Matcher *>::iterator> matchers() {
377*0fca6ea1SDimitry Andric     return make_range(Matchers.begin(), Matchers.end());
378*0fca6ea1SDimitry Andric   }
379*0fca6ea1SDimitry Andric   size_t size() const { return Matchers.size(); }
380*0fca6ea1SDimitry Andric   bool empty() const { return Matchers.empty(); }
381*0fca6ea1SDimitry Andric 
382*0fca6ea1SDimitry Andric   std::unique_ptr<PredicateMatcher> popFirstCondition() override {
383*0fca6ea1SDimitry Andric     assert(!Conditions.empty() &&
384*0fca6ea1SDimitry Andric            "Trying to pop a condition from a condition-less group");
385*0fca6ea1SDimitry Andric     std::unique_ptr<PredicateMatcher> P = std::move(Conditions.front());
386*0fca6ea1SDimitry Andric     Conditions.erase(Conditions.begin());
387*0fca6ea1SDimitry Andric     return P;
388*0fca6ea1SDimitry Andric   }
389*0fca6ea1SDimitry Andric   const PredicateMatcher &getFirstCondition() const override {
390*0fca6ea1SDimitry Andric     assert(!Conditions.empty() &&
391*0fca6ea1SDimitry Andric            "Trying to get a condition from a condition-less group");
392*0fca6ea1SDimitry Andric     return *Conditions.front();
393*0fca6ea1SDimitry Andric   }
394*0fca6ea1SDimitry Andric   bool hasFirstCondition() const override { return !Conditions.empty(); }
395*0fca6ea1SDimitry Andric 
396*0fca6ea1SDimitry Andric private:
397*0fca6ea1SDimitry Andric   /// See if a candidate matcher could be added to this group solely by
398*0fca6ea1SDimitry Andric   /// analyzing its first condition.
399*0fca6ea1SDimitry Andric   bool candidateConditionMatches(const PredicateMatcher &Predicate) const;
400*0fca6ea1SDimitry Andric };
401*0fca6ea1SDimitry Andric 
402*0fca6ea1SDimitry Andric class SwitchMatcher : public Matcher {
403*0fca6ea1SDimitry Andric   /// All the nested matchers, representing distinct switch-cases. The first
404*0fca6ea1SDimitry Andric   /// conditions (as Matcher::getFirstCondition() reports) of all the nested
405*0fca6ea1SDimitry Andric   /// matchers must share the same type and path to a value they check, in other
406*0fca6ea1SDimitry Andric   /// words, be isIdenticalDownToValue, but have different values they check
407*0fca6ea1SDimitry Andric   /// against.
408*0fca6ea1SDimitry Andric   std::vector<Matcher *> Matchers;
409*0fca6ea1SDimitry Andric 
410*0fca6ea1SDimitry Andric   /// The representative condition, with a type and a path (InsnVarID and OpIdx
411*0fca6ea1SDimitry Andric   /// in most cases)  shared by all the matchers contained.
412*0fca6ea1SDimitry Andric   std::unique_ptr<PredicateMatcher> Condition = nullptr;
413*0fca6ea1SDimitry Andric 
414*0fca6ea1SDimitry Andric   /// Temporary set used to check that the case values don't repeat within the
415*0fca6ea1SDimitry Andric   /// same switch.
416*0fca6ea1SDimitry Andric   std::set<MatchTableRecord> Values;
417*0fca6ea1SDimitry Andric 
418*0fca6ea1SDimitry Andric   /// An owning collection for any auxiliary matchers created while optimizing
419*0fca6ea1SDimitry Andric   /// nested matchers contained.
420*0fca6ea1SDimitry Andric   std::vector<std::unique_ptr<Matcher>> MatcherStorage;
421*0fca6ea1SDimitry Andric 
422*0fca6ea1SDimitry Andric public:
423*0fca6ea1SDimitry Andric   bool addMatcher(Matcher &Candidate);
424*0fca6ea1SDimitry Andric 
425*0fca6ea1SDimitry Andric   void finalize();
426*0fca6ea1SDimitry Andric   void emit(MatchTable &Table) override;
427*0fca6ea1SDimitry Andric 
428*0fca6ea1SDimitry Andric   iterator_range<std::vector<Matcher *>::iterator> matchers() {
429*0fca6ea1SDimitry Andric     return make_range(Matchers.begin(), Matchers.end());
430*0fca6ea1SDimitry Andric   }
431*0fca6ea1SDimitry Andric   size_t size() const { return Matchers.size(); }
432*0fca6ea1SDimitry Andric   bool empty() const { return Matchers.empty(); }
433*0fca6ea1SDimitry Andric 
434*0fca6ea1SDimitry Andric   std::unique_ptr<PredicateMatcher> popFirstCondition() override {
435*0fca6ea1SDimitry Andric     // SwitchMatcher doesn't have a common first condition for its cases, as all
436*0fca6ea1SDimitry Andric     // the cases only share a kind of a value (a type and a path to it) they
437*0fca6ea1SDimitry Andric     // match, but deliberately differ in the actual value they match.
438*0fca6ea1SDimitry Andric     llvm_unreachable("Trying to pop a condition from a condition-less group");
439*0fca6ea1SDimitry Andric   }
440*0fca6ea1SDimitry Andric 
441*0fca6ea1SDimitry Andric   const PredicateMatcher &getFirstCondition() const override {
442*0fca6ea1SDimitry Andric     llvm_unreachable("Trying to pop a condition from a condition-less group");
443*0fca6ea1SDimitry Andric   }
444*0fca6ea1SDimitry Andric 
445*0fca6ea1SDimitry Andric   bool hasFirstCondition() const override { return false; }
446*0fca6ea1SDimitry Andric 
447*0fca6ea1SDimitry Andric private:
448*0fca6ea1SDimitry Andric   /// See if the predicate type has a Switch-implementation for it.
449*0fca6ea1SDimitry Andric   static bool isSupportedPredicateType(const PredicateMatcher &Predicate);
450*0fca6ea1SDimitry Andric 
451*0fca6ea1SDimitry Andric   bool candidateConditionMatches(const PredicateMatcher &Predicate) const;
452*0fca6ea1SDimitry Andric 
453*0fca6ea1SDimitry Andric   /// emit()-helper
454*0fca6ea1SDimitry Andric   static void emitPredicateSpecificOpcodes(const PredicateMatcher &P,
455*0fca6ea1SDimitry Andric                                            MatchTable &Table);
456*0fca6ea1SDimitry Andric };
457*0fca6ea1SDimitry Andric 
458*0fca6ea1SDimitry Andric /// Generates code to check that a match rule matches.
459*0fca6ea1SDimitry Andric class RuleMatcher : public Matcher {
460*0fca6ea1SDimitry Andric public:
461*0fca6ea1SDimitry Andric   using ActionList = std::list<std::unique_ptr<MatchAction>>;
462*0fca6ea1SDimitry Andric   using action_iterator = ActionList::iterator;
463*0fca6ea1SDimitry Andric 
464*0fca6ea1SDimitry Andric protected:
465*0fca6ea1SDimitry Andric   /// A list of matchers that all need to succeed for the current rule to match.
466*0fca6ea1SDimitry Andric   /// FIXME: This currently supports a single match position but could be
467*0fca6ea1SDimitry Andric   /// extended to support multiple positions to support div/rem fusion or
468*0fca6ea1SDimitry Andric   /// load-multiple instructions.
469*0fca6ea1SDimitry Andric   using MatchersTy = std::vector<std::unique_ptr<InstructionMatcher>>;
470*0fca6ea1SDimitry Andric   MatchersTy Matchers;
471*0fca6ea1SDimitry Andric 
472*0fca6ea1SDimitry Andric   /// A list of actions that need to be taken when all predicates in this rule
473*0fca6ea1SDimitry Andric   /// have succeeded.
474*0fca6ea1SDimitry Andric   ActionList Actions;
475*0fca6ea1SDimitry Andric 
476*0fca6ea1SDimitry Andric   /// Combiners can sometimes just run C++ code to finish matching a rule &
477*0fca6ea1SDimitry Andric   /// mutate instructions instead of relying on MatchActions. Empty if unused.
478*0fca6ea1SDimitry Andric   std::string CustomCXXAction;
479*0fca6ea1SDimitry Andric 
480*0fca6ea1SDimitry Andric   using DefinedInsnVariablesMap = std::map<InstructionMatcher *, unsigned>;
481*0fca6ea1SDimitry Andric 
482*0fca6ea1SDimitry Andric   /// A map of instruction matchers to the local variables
483*0fca6ea1SDimitry Andric   DefinedInsnVariablesMap InsnVariableIDs;
484*0fca6ea1SDimitry Andric 
485*0fca6ea1SDimitry Andric   using MutatableInsnSet = SmallPtrSet<InstructionMatcher *, 4>;
486*0fca6ea1SDimitry Andric 
487*0fca6ea1SDimitry Andric   // The set of instruction matchers that have not yet been claimed for mutation
488*0fca6ea1SDimitry Andric   // by a BuildMI.
489*0fca6ea1SDimitry Andric   MutatableInsnSet MutatableInsns;
490*0fca6ea1SDimitry Andric 
491*0fca6ea1SDimitry Andric   /// A map of named operands defined by the matchers that may be referenced by
492*0fca6ea1SDimitry Andric   /// the renderers.
493*0fca6ea1SDimitry Andric   StringMap<OperandMatcher *> DefinedOperands;
494*0fca6ea1SDimitry Andric 
495*0fca6ea1SDimitry Andric   /// A map of anonymous physical register operands defined by the matchers that
496*0fca6ea1SDimitry Andric   /// may be referenced by the renderers.
497*0fca6ea1SDimitry Andric   DenseMap<Record *, OperandMatcher *> PhysRegOperands;
498*0fca6ea1SDimitry Andric 
499*0fca6ea1SDimitry Andric   /// ID for the next instruction variable defined with
500*0fca6ea1SDimitry Andric   /// implicitlyDefineInsnVar()
501*0fca6ea1SDimitry Andric   unsigned NextInsnVarID;
502*0fca6ea1SDimitry Andric 
503*0fca6ea1SDimitry Andric   /// ID for the next output instruction allocated with allocateOutputInsnID()
504*0fca6ea1SDimitry Andric   unsigned NextOutputInsnID;
505*0fca6ea1SDimitry Andric 
506*0fca6ea1SDimitry Andric   /// ID for the next temporary register ID allocated with allocateTempRegID()
507*0fca6ea1SDimitry Andric   unsigned NextTempRegID;
508*0fca6ea1SDimitry Andric 
509*0fca6ea1SDimitry Andric   /// ID for the next recorded type. Starts at -1 and counts down.
510*0fca6ea1SDimitry Andric   TempTypeIdx NextTempTypeIdx = -1;
511*0fca6ea1SDimitry Andric 
512*0fca6ea1SDimitry Andric   // HwMode predicate index for this rule. -1 if no HwMode.
513*0fca6ea1SDimitry Andric   int HwModeIdx = -1;
514*0fca6ea1SDimitry Andric 
515*0fca6ea1SDimitry Andric   /// Current GISelFlags
516*0fca6ea1SDimitry Andric   GISelFlags Flags = 0;
517*0fca6ea1SDimitry Andric 
518*0fca6ea1SDimitry Andric   std::vector<std::string> RequiredSimplePredicates;
519*0fca6ea1SDimitry Andric   std::vector<Record *> RequiredFeatures;
520*0fca6ea1SDimitry Andric   std::vector<std::unique_ptr<PredicateMatcher>> EpilogueMatchers;
521*0fca6ea1SDimitry Andric 
522*0fca6ea1SDimitry Andric   DenseSet<unsigned> ErasedInsnIDs;
523*0fca6ea1SDimitry Andric 
524*0fca6ea1SDimitry Andric   ArrayRef<SMLoc> SrcLoc;
525*0fca6ea1SDimitry Andric 
526*0fca6ea1SDimitry Andric   typedef std::tuple<Record *, unsigned, unsigned>
527*0fca6ea1SDimitry Andric       DefinedComplexPatternSubOperand;
528*0fca6ea1SDimitry Andric   typedef StringMap<DefinedComplexPatternSubOperand>
529*0fca6ea1SDimitry Andric       DefinedComplexPatternSubOperandMap;
530*0fca6ea1SDimitry Andric   /// A map of Symbolic Names to ComplexPattern sub-operands.
531*0fca6ea1SDimitry Andric   DefinedComplexPatternSubOperandMap ComplexSubOperands;
532*0fca6ea1SDimitry Andric   /// A map used to for multiple referenced error check of ComplexSubOperand.
533*0fca6ea1SDimitry Andric   /// ComplexSubOperand can't be referenced multiple from different operands,
534*0fca6ea1SDimitry Andric   /// however multiple references from same operand are allowed since that is
535*0fca6ea1SDimitry Andric   /// how 'same operand checks' are generated.
536*0fca6ea1SDimitry Andric   StringMap<std::string> ComplexSubOperandsParentName;
537*0fca6ea1SDimitry Andric 
538*0fca6ea1SDimitry Andric   uint64_t RuleID;
539*0fca6ea1SDimitry Andric   static uint64_t NextRuleID;
540*0fca6ea1SDimitry Andric 
541*0fca6ea1SDimitry Andric   GISelFlags updateGISelFlag(GISelFlags CurFlags, const Record *R,
542*0fca6ea1SDimitry Andric                              StringRef FlagName, GISelFlags FlagBit);
543*0fca6ea1SDimitry Andric 
544*0fca6ea1SDimitry Andric public:
545*0fca6ea1SDimitry Andric   RuleMatcher(ArrayRef<SMLoc> SrcLoc)
546*0fca6ea1SDimitry Andric       : NextInsnVarID(0), NextOutputInsnID(0), NextTempRegID(0), SrcLoc(SrcLoc),
547*0fca6ea1SDimitry Andric         RuleID(NextRuleID++) {}
548*0fca6ea1SDimitry Andric   RuleMatcher(RuleMatcher &&Other) = default;
549*0fca6ea1SDimitry Andric   RuleMatcher &operator=(RuleMatcher &&Other) = default;
550*0fca6ea1SDimitry Andric 
551*0fca6ea1SDimitry Andric   TempTypeIdx getNextTempTypeIdx() { return NextTempTypeIdx--; }
552*0fca6ea1SDimitry Andric 
553*0fca6ea1SDimitry Andric   uint64_t getRuleID() const { return RuleID; }
554*0fca6ea1SDimitry Andric 
555*0fca6ea1SDimitry Andric   InstructionMatcher &addInstructionMatcher(StringRef SymbolicName);
556*0fca6ea1SDimitry Andric   void addRequiredFeature(Record *Feature);
557*0fca6ea1SDimitry Andric   const std::vector<Record *> &getRequiredFeatures() const;
558*0fca6ea1SDimitry Andric 
559*0fca6ea1SDimitry Andric   void addHwModeIdx(unsigned Idx) { HwModeIdx = Idx; }
560*0fca6ea1SDimitry Andric   int getHwModeIdx() const { return HwModeIdx; }
561*0fca6ea1SDimitry Andric 
562*0fca6ea1SDimitry Andric   void addRequiredSimplePredicate(StringRef PredName);
563*0fca6ea1SDimitry Andric   const std::vector<std::string> &getRequiredSimplePredicates();
564*0fca6ea1SDimitry Andric 
565*0fca6ea1SDimitry Andric   /// Attempts to mark \p ID as erased (GIR_EraseFromParent called on it).
566*0fca6ea1SDimitry Andric   /// If \p ID has already been erased, returns false and GIR_EraseFromParent
567*0fca6ea1SDimitry Andric   /// should NOT be emitted.
568*0fca6ea1SDimitry Andric   bool tryEraseInsnID(unsigned ID) { return ErasedInsnIDs.insert(ID).second; }
569*0fca6ea1SDimitry Andric 
570*0fca6ea1SDimitry Andric   void setCustomCXXAction(StringRef FnEnumName) {
571*0fca6ea1SDimitry Andric     CustomCXXAction = FnEnumName.str();
572*0fca6ea1SDimitry Andric   }
573*0fca6ea1SDimitry Andric 
574*0fca6ea1SDimitry Andric   // Emplaces an action of the specified Kind at the end of the action list.
575*0fca6ea1SDimitry Andric   //
576*0fca6ea1SDimitry Andric   // Returns a reference to the newly created action.
577*0fca6ea1SDimitry Andric   //
578*0fca6ea1SDimitry Andric   // Like std::vector::emplace_back(), may invalidate all iterators if the new
579*0fca6ea1SDimitry Andric   // size exceeds the capacity. Otherwise, only invalidates the past-the-end
580*0fca6ea1SDimitry Andric   // iterator.
581*0fca6ea1SDimitry Andric   template <class Kind, class... Args> Kind &addAction(Args &&...args) {
582*0fca6ea1SDimitry Andric     Actions.emplace_back(std::make_unique<Kind>(std::forward<Args>(args)...));
583*0fca6ea1SDimitry Andric     return *static_cast<Kind *>(Actions.back().get());
584*0fca6ea1SDimitry Andric   }
585*0fca6ea1SDimitry Andric 
586*0fca6ea1SDimitry Andric   // Emplaces an action of the specified Kind before the given insertion point.
587*0fca6ea1SDimitry Andric   //
588*0fca6ea1SDimitry Andric   // Returns an iterator pointing at the newly created instruction.
589*0fca6ea1SDimitry Andric   //
590*0fca6ea1SDimitry Andric   // Like std::vector::insert(), may invalidate all iterators if the new size
591*0fca6ea1SDimitry Andric   // exceeds the capacity. Otherwise, only invalidates the iterators from the
592*0fca6ea1SDimitry Andric   // insertion point onwards.
593*0fca6ea1SDimitry Andric   template <class Kind, class... Args>
594*0fca6ea1SDimitry Andric   action_iterator insertAction(action_iterator InsertPt, Args &&...args) {
595*0fca6ea1SDimitry Andric     return Actions.emplace(InsertPt,
596*0fca6ea1SDimitry Andric                            std::make_unique<Kind>(std::forward<Args>(args)...));
597*0fca6ea1SDimitry Andric   }
598*0fca6ea1SDimitry Andric 
599*0fca6ea1SDimitry Andric   void setPermanentGISelFlags(GISelFlags V) { Flags = V; }
600*0fca6ea1SDimitry Andric 
601*0fca6ea1SDimitry Andric   // Update the active GISelFlags based on the GISelFlags Record R.
602*0fca6ea1SDimitry Andric   // A SaveAndRestore object is returned so the old GISelFlags are restored
603*0fca6ea1SDimitry Andric   // at the end of the scope.
604*0fca6ea1SDimitry Andric   SaveAndRestore<GISelFlags> setGISelFlags(const Record *R);
605*0fca6ea1SDimitry Andric   GISelFlags getGISelFlags() const { return Flags; }
606*0fca6ea1SDimitry Andric 
607*0fca6ea1SDimitry Andric   /// Define an instruction without emitting any code to do so.
608*0fca6ea1SDimitry Andric   unsigned implicitlyDefineInsnVar(InstructionMatcher &Matcher);
609*0fca6ea1SDimitry Andric 
610*0fca6ea1SDimitry Andric   unsigned getInsnVarID(InstructionMatcher &InsnMatcher) const;
611*0fca6ea1SDimitry Andric   DefinedInsnVariablesMap::const_iterator defined_insn_vars_begin() const {
612*0fca6ea1SDimitry Andric     return InsnVariableIDs.begin();
613*0fca6ea1SDimitry Andric   }
614*0fca6ea1SDimitry Andric   DefinedInsnVariablesMap::const_iterator defined_insn_vars_end() const {
615*0fca6ea1SDimitry Andric     return InsnVariableIDs.end();
616*0fca6ea1SDimitry Andric   }
617*0fca6ea1SDimitry Andric   iterator_range<typename DefinedInsnVariablesMap::const_iterator>
618*0fca6ea1SDimitry Andric   defined_insn_vars() const {
619*0fca6ea1SDimitry Andric     return make_range(defined_insn_vars_begin(), defined_insn_vars_end());
620*0fca6ea1SDimitry Andric   }
621*0fca6ea1SDimitry Andric 
622*0fca6ea1SDimitry Andric   MutatableInsnSet::const_iterator mutatable_insns_begin() const {
623*0fca6ea1SDimitry Andric     return MutatableInsns.begin();
624*0fca6ea1SDimitry Andric   }
625*0fca6ea1SDimitry Andric   MutatableInsnSet::const_iterator mutatable_insns_end() const {
626*0fca6ea1SDimitry Andric     return MutatableInsns.end();
627*0fca6ea1SDimitry Andric   }
628*0fca6ea1SDimitry Andric   iterator_range<typename MutatableInsnSet::const_iterator>
629*0fca6ea1SDimitry Andric   mutatable_insns() const {
630*0fca6ea1SDimitry Andric     return make_range(mutatable_insns_begin(), mutatable_insns_end());
631*0fca6ea1SDimitry Andric   }
632*0fca6ea1SDimitry Andric   void reserveInsnMatcherForMutation(InstructionMatcher *InsnMatcher) {
633*0fca6ea1SDimitry Andric     bool R = MutatableInsns.erase(InsnMatcher);
634*0fca6ea1SDimitry Andric     assert(R && "Reserving a mutatable insn that isn't available");
635*0fca6ea1SDimitry Andric     (void)R;
636*0fca6ea1SDimitry Andric   }
637*0fca6ea1SDimitry Andric 
638*0fca6ea1SDimitry Andric   action_iterator actions_begin() { return Actions.begin(); }
639*0fca6ea1SDimitry Andric   action_iterator actions_end() { return Actions.end(); }
640*0fca6ea1SDimitry Andric   iterator_range<action_iterator> actions() {
641*0fca6ea1SDimitry Andric     return make_range(actions_begin(), actions_end());
642*0fca6ea1SDimitry Andric   }
643*0fca6ea1SDimitry Andric 
644*0fca6ea1SDimitry Andric   void defineOperand(StringRef SymbolicName, OperandMatcher &OM);
645*0fca6ea1SDimitry Andric 
646*0fca6ea1SDimitry Andric   void definePhysRegOperand(Record *Reg, OperandMatcher &OM);
647*0fca6ea1SDimitry Andric 
648*0fca6ea1SDimitry Andric   Error defineComplexSubOperand(StringRef SymbolicName, Record *ComplexPattern,
649*0fca6ea1SDimitry Andric                                 unsigned RendererID, unsigned SubOperandID,
650*0fca6ea1SDimitry Andric                                 StringRef ParentSymbolicName);
651*0fca6ea1SDimitry Andric 
652*0fca6ea1SDimitry Andric   std::optional<DefinedComplexPatternSubOperand>
653*0fca6ea1SDimitry Andric   getComplexSubOperand(StringRef SymbolicName) const {
654*0fca6ea1SDimitry Andric     const auto &I = ComplexSubOperands.find(SymbolicName);
655*0fca6ea1SDimitry Andric     if (I == ComplexSubOperands.end())
656*0fca6ea1SDimitry Andric       return std::nullopt;
657*0fca6ea1SDimitry Andric     return I->second;
658*0fca6ea1SDimitry Andric   }
659*0fca6ea1SDimitry Andric 
660*0fca6ea1SDimitry Andric   InstructionMatcher &getInstructionMatcher(StringRef SymbolicName) const;
661*0fca6ea1SDimitry Andric   OperandMatcher &getOperandMatcher(StringRef Name);
662*0fca6ea1SDimitry Andric   const OperandMatcher &getOperandMatcher(StringRef Name) const;
663*0fca6ea1SDimitry Andric   const OperandMatcher &getPhysRegOperandMatcher(Record *) const;
664*0fca6ea1SDimitry Andric 
665*0fca6ea1SDimitry Andric   void optimize() override;
666*0fca6ea1SDimitry Andric   void emit(MatchTable &Table) override;
667*0fca6ea1SDimitry Andric 
668*0fca6ea1SDimitry Andric   /// Compare the priority of this object and B.
669*0fca6ea1SDimitry Andric   ///
670*0fca6ea1SDimitry Andric   /// Returns true if this object is more important than B.
671*0fca6ea1SDimitry Andric   bool isHigherPriorityThan(const RuleMatcher &B) const;
672*0fca6ea1SDimitry Andric 
673*0fca6ea1SDimitry Andric   /// Report the maximum number of temporary operands needed by the rule
674*0fca6ea1SDimitry Andric   /// matcher.
675*0fca6ea1SDimitry Andric   unsigned countRendererFns() const;
676*0fca6ea1SDimitry Andric 
677*0fca6ea1SDimitry Andric   std::unique_ptr<PredicateMatcher> popFirstCondition() override;
678*0fca6ea1SDimitry Andric   const PredicateMatcher &getFirstCondition() const override;
679*0fca6ea1SDimitry Andric   LLTCodeGen getFirstConditionAsRootType();
680*0fca6ea1SDimitry Andric   bool hasFirstCondition() const override;
681*0fca6ea1SDimitry Andric   unsigned getNumOperands() const;
682*0fca6ea1SDimitry Andric   StringRef getOpcode() const;
683*0fca6ea1SDimitry Andric 
684*0fca6ea1SDimitry Andric   // FIXME: Remove this as soon as possible
685*0fca6ea1SDimitry Andric   InstructionMatcher &insnmatchers_front() const { return *Matchers.front(); }
686*0fca6ea1SDimitry Andric 
687*0fca6ea1SDimitry Andric   unsigned allocateOutputInsnID() { return NextOutputInsnID++; }
688*0fca6ea1SDimitry Andric   unsigned allocateTempRegID() { return NextTempRegID++; }
689*0fca6ea1SDimitry Andric 
690*0fca6ea1SDimitry Andric   iterator_range<MatchersTy::iterator> insnmatchers() {
691*0fca6ea1SDimitry Andric     return make_range(Matchers.begin(), Matchers.end());
692*0fca6ea1SDimitry Andric   }
693*0fca6ea1SDimitry Andric   bool insnmatchers_empty() const { return Matchers.empty(); }
694*0fca6ea1SDimitry Andric   void insnmatchers_pop_front() { Matchers.erase(Matchers.begin()); }
695*0fca6ea1SDimitry Andric };
696*0fca6ea1SDimitry Andric 
697*0fca6ea1SDimitry Andric template <class PredicateTy> class PredicateListMatcher {
698*0fca6ea1SDimitry Andric private:
699*0fca6ea1SDimitry Andric   /// Template instantiations should specialize this to return a string to use
700*0fca6ea1SDimitry Andric   /// for the comment emitted when there are no predicates.
701*0fca6ea1SDimitry Andric   std::string getNoPredicateComment() const;
702*0fca6ea1SDimitry Andric 
703*0fca6ea1SDimitry Andric protected:
704*0fca6ea1SDimitry Andric   using PredicatesTy = std::deque<std::unique_ptr<PredicateTy>>;
705*0fca6ea1SDimitry Andric   PredicatesTy Predicates;
706*0fca6ea1SDimitry Andric 
707*0fca6ea1SDimitry Andric   /// Track if the list of predicates was manipulated by one of the optimization
708*0fca6ea1SDimitry Andric   /// methods.
709*0fca6ea1SDimitry Andric   bool Optimized = false;
710*0fca6ea1SDimitry Andric 
711*0fca6ea1SDimitry Andric public:
712*0fca6ea1SDimitry Andric   typename PredicatesTy::iterator predicates_begin() {
713*0fca6ea1SDimitry Andric     return Predicates.begin();
714*0fca6ea1SDimitry Andric   }
715*0fca6ea1SDimitry Andric   typename PredicatesTy::iterator predicates_end() { return Predicates.end(); }
716*0fca6ea1SDimitry Andric   iterator_range<typename PredicatesTy::iterator> predicates() {
717*0fca6ea1SDimitry Andric     return make_range(predicates_begin(), predicates_end());
718*0fca6ea1SDimitry Andric   }
719*0fca6ea1SDimitry Andric   typename PredicatesTy::size_type predicates_size() const {
720*0fca6ea1SDimitry Andric     return Predicates.size();
721*0fca6ea1SDimitry Andric   }
722*0fca6ea1SDimitry Andric   bool predicates_empty() const { return Predicates.empty(); }
723*0fca6ea1SDimitry Andric 
724*0fca6ea1SDimitry Andric   template <typename Ty> bool contains() const {
725*0fca6ea1SDimitry Andric     return any_of(Predicates, [&](auto &P) { return isa<Ty>(P.get()); });
726*0fca6ea1SDimitry Andric   }
727*0fca6ea1SDimitry Andric 
728*0fca6ea1SDimitry Andric   std::unique_ptr<PredicateTy> predicates_pop_front() {
729*0fca6ea1SDimitry Andric     std::unique_ptr<PredicateTy> Front = std::move(Predicates.front());
730*0fca6ea1SDimitry Andric     Predicates.pop_front();
731*0fca6ea1SDimitry Andric     Optimized = true;
732*0fca6ea1SDimitry Andric     return Front;
733*0fca6ea1SDimitry Andric   }
734*0fca6ea1SDimitry Andric 
735*0fca6ea1SDimitry Andric   void prependPredicate(std::unique_ptr<PredicateTy> &&Predicate) {
736*0fca6ea1SDimitry Andric     Predicates.push_front(std::move(Predicate));
737*0fca6ea1SDimitry Andric   }
738*0fca6ea1SDimitry Andric 
739*0fca6ea1SDimitry Andric   void eraseNullPredicates() {
740*0fca6ea1SDimitry Andric     const auto NewEnd =
741*0fca6ea1SDimitry Andric         std::stable_partition(Predicates.begin(), Predicates.end(),
742*0fca6ea1SDimitry Andric                               std::logical_not<std::unique_ptr<PredicateTy>>());
743*0fca6ea1SDimitry Andric     if (NewEnd != Predicates.begin()) {
744*0fca6ea1SDimitry Andric       Predicates.erase(Predicates.begin(), NewEnd);
745*0fca6ea1SDimitry Andric       Optimized = true;
746*0fca6ea1SDimitry Andric     }
747*0fca6ea1SDimitry Andric   }
748*0fca6ea1SDimitry Andric 
749*0fca6ea1SDimitry Andric   /// Emit MatchTable opcodes that tests whether all the predicates are met.
750*0fca6ea1SDimitry Andric   template <class... Args>
751*0fca6ea1SDimitry Andric   void emitPredicateListOpcodes(MatchTable &Table, Args &&...args) {
752*0fca6ea1SDimitry Andric     if (Predicates.empty() && !Optimized) {
753*0fca6ea1SDimitry Andric       Table << MatchTable::Comment(getNoPredicateComment())
754*0fca6ea1SDimitry Andric             << MatchTable::LineBreak;
755*0fca6ea1SDimitry Andric       return;
756*0fca6ea1SDimitry Andric     }
757*0fca6ea1SDimitry Andric 
758*0fca6ea1SDimitry Andric     for (const auto &Predicate : predicates())
759*0fca6ea1SDimitry Andric       Predicate->emitPredicateOpcodes(Table, std::forward<Args>(args)...);
760*0fca6ea1SDimitry Andric   }
761*0fca6ea1SDimitry Andric 
762*0fca6ea1SDimitry Andric   /// Provide a function to avoid emitting certain predicates. This is used to
763*0fca6ea1SDimitry Andric   /// defer some predicate checks until after others
764*0fca6ea1SDimitry Andric   using PredicateFilterFunc = std::function<bool(const PredicateTy &)>;
765*0fca6ea1SDimitry Andric 
766*0fca6ea1SDimitry Andric   /// Emit MatchTable opcodes for predicates which satisfy \p
767*0fca6ea1SDimitry Andric   /// ShouldEmitPredicate. This should be called multiple times to ensure all
768*0fca6ea1SDimitry Andric   /// predicates are eventually added to the match table.
769*0fca6ea1SDimitry Andric   template <class... Args>
770*0fca6ea1SDimitry Andric   void emitFilteredPredicateListOpcodes(PredicateFilterFunc ShouldEmitPredicate,
771*0fca6ea1SDimitry Andric                                         MatchTable &Table, Args &&...args) {
772*0fca6ea1SDimitry Andric     if (Predicates.empty() && !Optimized) {
773*0fca6ea1SDimitry Andric       Table << MatchTable::Comment(getNoPredicateComment())
774*0fca6ea1SDimitry Andric             << MatchTable::LineBreak;
775*0fca6ea1SDimitry Andric       return;
776*0fca6ea1SDimitry Andric     }
777*0fca6ea1SDimitry Andric 
778*0fca6ea1SDimitry Andric     for (const auto &Predicate : predicates()) {
779*0fca6ea1SDimitry Andric       if (ShouldEmitPredicate(*Predicate))
780*0fca6ea1SDimitry Andric         Predicate->emitPredicateOpcodes(Table, std::forward<Args>(args)...);
781*0fca6ea1SDimitry Andric     }
782*0fca6ea1SDimitry Andric   }
783*0fca6ea1SDimitry Andric };
784*0fca6ea1SDimitry Andric 
785*0fca6ea1SDimitry Andric class PredicateMatcher {
786*0fca6ea1SDimitry Andric public:
787*0fca6ea1SDimitry Andric   /// This enum is used for RTTI and also defines the priority that is given to
788*0fca6ea1SDimitry Andric   /// the predicate when generating the matcher code. Kinds with higher priority
789*0fca6ea1SDimitry Andric   /// must be tested first.
790*0fca6ea1SDimitry Andric   ///
791*0fca6ea1SDimitry Andric   /// The relative priority of OPM_LLT, OPM_RegBank, and OPM_MBB do not matter
792*0fca6ea1SDimitry Andric   /// but OPM_Int must have priority over OPM_RegBank since constant integers
793*0fca6ea1SDimitry Andric   /// are represented by a virtual register defined by a G_CONSTANT instruction.
794*0fca6ea1SDimitry Andric   ///
795*0fca6ea1SDimitry Andric   /// Note: The relative priority between IPM_ and OPM_ does not matter, they
796*0fca6ea1SDimitry Andric   /// are currently not compared between each other.
797*0fca6ea1SDimitry Andric   enum PredicateKind {
798*0fca6ea1SDimitry Andric     IPM_Opcode,
799*0fca6ea1SDimitry Andric     IPM_NumOperands,
800*0fca6ea1SDimitry Andric     IPM_ImmPredicate,
801*0fca6ea1SDimitry Andric     IPM_Imm,
802*0fca6ea1SDimitry Andric     IPM_AtomicOrderingMMO,
803*0fca6ea1SDimitry Andric     IPM_MemoryLLTSize,
804*0fca6ea1SDimitry Andric     IPM_MemoryVsLLTSize,
805*0fca6ea1SDimitry Andric     IPM_MemoryAddressSpace,
806*0fca6ea1SDimitry Andric     IPM_MemoryAlignment,
807*0fca6ea1SDimitry Andric     IPM_VectorSplatImm,
808*0fca6ea1SDimitry Andric     IPM_NoUse,
809*0fca6ea1SDimitry Andric     IPM_OneUse,
810*0fca6ea1SDimitry Andric     IPM_GenericPredicate,
811*0fca6ea1SDimitry Andric     IPM_MIFlags,
812*0fca6ea1SDimitry Andric     OPM_SameOperand,
813*0fca6ea1SDimitry Andric     OPM_ComplexPattern,
814*0fca6ea1SDimitry Andric     OPM_IntrinsicID,
815*0fca6ea1SDimitry Andric     OPM_CmpPredicate,
816*0fca6ea1SDimitry Andric     OPM_Instruction,
817*0fca6ea1SDimitry Andric     OPM_Int,
818*0fca6ea1SDimitry Andric     OPM_LiteralInt,
819*0fca6ea1SDimitry Andric     OPM_LLT,
820*0fca6ea1SDimitry Andric     OPM_PointerToAny,
821*0fca6ea1SDimitry Andric     OPM_RegBank,
822*0fca6ea1SDimitry Andric     OPM_MBB,
823*0fca6ea1SDimitry Andric     OPM_RecordNamedOperand,
824*0fca6ea1SDimitry Andric     OPM_RecordRegType,
825*0fca6ea1SDimitry Andric   };
826*0fca6ea1SDimitry Andric 
827*0fca6ea1SDimitry Andric protected:
828*0fca6ea1SDimitry Andric   PredicateKind Kind;
829*0fca6ea1SDimitry Andric   unsigned InsnVarID;
830*0fca6ea1SDimitry Andric   unsigned OpIdx;
831*0fca6ea1SDimitry Andric 
832*0fca6ea1SDimitry Andric public:
833*0fca6ea1SDimitry Andric   PredicateMatcher(PredicateKind Kind, unsigned InsnVarID, unsigned OpIdx = ~0)
834*0fca6ea1SDimitry Andric       : Kind(Kind), InsnVarID(InsnVarID), OpIdx(OpIdx) {}
835*0fca6ea1SDimitry Andric   virtual ~PredicateMatcher();
836*0fca6ea1SDimitry Andric 
837*0fca6ea1SDimitry Andric   unsigned getInsnVarID() const { return InsnVarID; }
838*0fca6ea1SDimitry Andric   unsigned getOpIdx() const { return OpIdx; }
839*0fca6ea1SDimitry Andric 
840*0fca6ea1SDimitry Andric   /// Emit MatchTable opcodes that check the predicate for the given operand.
841*0fca6ea1SDimitry Andric   virtual void emitPredicateOpcodes(MatchTable &Table,
842*0fca6ea1SDimitry Andric                                     RuleMatcher &Rule) const = 0;
843*0fca6ea1SDimitry Andric 
844*0fca6ea1SDimitry Andric   PredicateKind getKind() const { return Kind; }
845*0fca6ea1SDimitry Andric 
846*0fca6ea1SDimitry Andric   bool dependsOnOperands() const {
847*0fca6ea1SDimitry Andric     // Custom predicates really depend on the context pattern of the
848*0fca6ea1SDimitry Andric     // instruction, not just the individual instruction. This therefore
849*0fca6ea1SDimitry Andric     // implicitly depends on all other pattern constraints.
850*0fca6ea1SDimitry Andric     return Kind == IPM_GenericPredicate;
851*0fca6ea1SDimitry Andric   }
852*0fca6ea1SDimitry Andric 
853*0fca6ea1SDimitry Andric   virtual bool isIdentical(const PredicateMatcher &B) const {
854*0fca6ea1SDimitry Andric     return B.getKind() == getKind() && InsnVarID == B.InsnVarID &&
855*0fca6ea1SDimitry Andric            OpIdx == B.OpIdx;
856*0fca6ea1SDimitry Andric   }
857*0fca6ea1SDimitry Andric 
858*0fca6ea1SDimitry Andric   virtual bool isIdenticalDownToValue(const PredicateMatcher &B) const {
859*0fca6ea1SDimitry Andric     return hasValue() && PredicateMatcher::isIdentical(B);
860*0fca6ea1SDimitry Andric   }
861*0fca6ea1SDimitry Andric 
862*0fca6ea1SDimitry Andric   virtual MatchTableRecord getValue() const {
863*0fca6ea1SDimitry Andric     assert(hasValue() && "Can not get a value of a value-less predicate!");
864*0fca6ea1SDimitry Andric     llvm_unreachable("Not implemented yet");
865*0fca6ea1SDimitry Andric   }
866*0fca6ea1SDimitry Andric   virtual bool hasValue() const { return false; }
867*0fca6ea1SDimitry Andric 
868*0fca6ea1SDimitry Andric   /// Report the maximum number of temporary operands needed by the predicate
869*0fca6ea1SDimitry Andric   /// matcher.
870*0fca6ea1SDimitry Andric   virtual unsigned countRendererFns() const { return 0; }
871*0fca6ea1SDimitry Andric };
872*0fca6ea1SDimitry Andric 
873*0fca6ea1SDimitry Andric /// Generates code to check a predicate of an operand.
874*0fca6ea1SDimitry Andric ///
875*0fca6ea1SDimitry Andric /// Typical predicates include:
876*0fca6ea1SDimitry Andric /// * Operand is a particular register.
877*0fca6ea1SDimitry Andric /// * Operand is assigned a particular register bank.
878*0fca6ea1SDimitry Andric /// * Operand is an MBB.
879*0fca6ea1SDimitry Andric class OperandPredicateMatcher : public PredicateMatcher {
880*0fca6ea1SDimitry Andric public:
881*0fca6ea1SDimitry Andric   OperandPredicateMatcher(PredicateKind Kind, unsigned InsnVarID,
882*0fca6ea1SDimitry Andric                           unsigned OpIdx)
883*0fca6ea1SDimitry Andric       : PredicateMatcher(Kind, InsnVarID, OpIdx) {}
884*0fca6ea1SDimitry Andric   virtual ~OperandPredicateMatcher();
885*0fca6ea1SDimitry Andric 
886*0fca6ea1SDimitry Andric   /// Compare the priority of this object and B.
887*0fca6ea1SDimitry Andric   ///
888*0fca6ea1SDimitry Andric   /// Returns true if this object is more important than B.
889*0fca6ea1SDimitry Andric   virtual bool isHigherPriorityThan(const OperandPredicateMatcher &B) const;
890*0fca6ea1SDimitry Andric };
891*0fca6ea1SDimitry Andric 
892*0fca6ea1SDimitry Andric template <>
893*0fca6ea1SDimitry Andric inline std::string
894*0fca6ea1SDimitry Andric PredicateListMatcher<OperandPredicateMatcher>::getNoPredicateComment() const {
895*0fca6ea1SDimitry Andric   return "No operand predicates";
896*0fca6ea1SDimitry Andric }
897*0fca6ea1SDimitry Andric 
898*0fca6ea1SDimitry Andric /// Generates code to check that a register operand is defined by the same exact
899*0fca6ea1SDimitry Andric /// one as another.
900*0fca6ea1SDimitry Andric class SameOperandMatcher : public OperandPredicateMatcher {
901*0fca6ea1SDimitry Andric   std::string MatchingName;
902*0fca6ea1SDimitry Andric   unsigned OrigOpIdx;
903*0fca6ea1SDimitry Andric 
904*0fca6ea1SDimitry Andric   GISelFlags Flags;
905*0fca6ea1SDimitry Andric 
906*0fca6ea1SDimitry Andric public:
907*0fca6ea1SDimitry Andric   SameOperandMatcher(unsigned InsnVarID, unsigned OpIdx, StringRef MatchingName,
908*0fca6ea1SDimitry Andric                      unsigned OrigOpIdx, GISelFlags Flags)
909*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(OPM_SameOperand, InsnVarID, OpIdx),
910*0fca6ea1SDimitry Andric         MatchingName(MatchingName), OrigOpIdx(OrigOpIdx), Flags(Flags) {}
911*0fca6ea1SDimitry Andric 
912*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
913*0fca6ea1SDimitry Andric     return P->getKind() == OPM_SameOperand;
914*0fca6ea1SDimitry Andric   }
915*0fca6ea1SDimitry Andric 
916*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
917*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
918*0fca6ea1SDimitry Andric 
919*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
920*0fca6ea1SDimitry Andric     return OperandPredicateMatcher::isIdentical(B) &&
921*0fca6ea1SDimitry Andric            OrigOpIdx == cast<SameOperandMatcher>(&B)->OrigOpIdx &&
922*0fca6ea1SDimitry Andric            MatchingName == cast<SameOperandMatcher>(&B)->MatchingName;
923*0fca6ea1SDimitry Andric   }
924*0fca6ea1SDimitry Andric };
925*0fca6ea1SDimitry Andric 
926*0fca6ea1SDimitry Andric /// Generates code to check that an operand is a particular LLT.
927*0fca6ea1SDimitry Andric class LLTOperandMatcher : public OperandPredicateMatcher {
928*0fca6ea1SDimitry Andric protected:
929*0fca6ea1SDimitry Andric   LLTCodeGen Ty;
930*0fca6ea1SDimitry Andric 
931*0fca6ea1SDimitry Andric public:
932*0fca6ea1SDimitry Andric   static std::map<LLTCodeGen, unsigned> TypeIDValues;
933*0fca6ea1SDimitry Andric 
934*0fca6ea1SDimitry Andric   static void initTypeIDValuesMap() {
935*0fca6ea1SDimitry Andric     TypeIDValues.clear();
936*0fca6ea1SDimitry Andric 
937*0fca6ea1SDimitry Andric     unsigned ID = 0;
938*0fca6ea1SDimitry Andric     for (const LLTCodeGen &LLTy : KnownTypes)
939*0fca6ea1SDimitry Andric       TypeIDValues[LLTy] = ID++;
940*0fca6ea1SDimitry Andric   }
941*0fca6ea1SDimitry Andric 
942*0fca6ea1SDimitry Andric   LLTOperandMatcher(unsigned InsnVarID, unsigned OpIdx, const LLTCodeGen &Ty)
943*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(OPM_LLT, InsnVarID, OpIdx), Ty(Ty) {
944*0fca6ea1SDimitry Andric     KnownTypes.insert(Ty);
945*0fca6ea1SDimitry Andric   }
946*0fca6ea1SDimitry Andric 
947*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
948*0fca6ea1SDimitry Andric     return P->getKind() == OPM_LLT;
949*0fca6ea1SDimitry Andric   }
950*0fca6ea1SDimitry Andric 
951*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
952*0fca6ea1SDimitry Andric     return OperandPredicateMatcher::isIdentical(B) &&
953*0fca6ea1SDimitry Andric            Ty == cast<LLTOperandMatcher>(&B)->Ty;
954*0fca6ea1SDimitry Andric   }
955*0fca6ea1SDimitry Andric 
956*0fca6ea1SDimitry Andric   MatchTableRecord getValue() const override;
957*0fca6ea1SDimitry Andric   bool hasValue() const override;
958*0fca6ea1SDimitry Andric 
959*0fca6ea1SDimitry Andric   LLTCodeGen getTy() const { return Ty; }
960*0fca6ea1SDimitry Andric 
961*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
962*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
963*0fca6ea1SDimitry Andric };
964*0fca6ea1SDimitry Andric 
965*0fca6ea1SDimitry Andric /// Generates code to check that an operand is a pointer to any address space.
966*0fca6ea1SDimitry Andric ///
967*0fca6ea1SDimitry Andric /// In SelectionDAG, the types did not describe pointers or address spaces. As a
968*0fca6ea1SDimitry Andric /// result, iN is used to describe a pointer of N bits to any address space and
969*0fca6ea1SDimitry Andric /// PatFrag predicates are typically used to constrain the address space.
970*0fca6ea1SDimitry Andric /// There's no reliable means to derive the missing type information from the
971*0fca6ea1SDimitry Andric /// pattern so imported rules must test the components of a pointer separately.
972*0fca6ea1SDimitry Andric ///
973*0fca6ea1SDimitry Andric /// If SizeInBits is zero, then the pointer size will be obtained from the
974*0fca6ea1SDimitry Andric /// subtarget.
975*0fca6ea1SDimitry Andric class PointerToAnyOperandMatcher : public OperandPredicateMatcher {
976*0fca6ea1SDimitry Andric protected:
977*0fca6ea1SDimitry Andric   unsigned SizeInBits;
978*0fca6ea1SDimitry Andric 
979*0fca6ea1SDimitry Andric public:
980*0fca6ea1SDimitry Andric   PointerToAnyOperandMatcher(unsigned InsnVarID, unsigned OpIdx,
981*0fca6ea1SDimitry Andric                              unsigned SizeInBits)
982*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(OPM_PointerToAny, InsnVarID, OpIdx),
983*0fca6ea1SDimitry Andric         SizeInBits(SizeInBits) {}
984*0fca6ea1SDimitry Andric 
985*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
986*0fca6ea1SDimitry Andric     return P->getKind() == OPM_PointerToAny;
987*0fca6ea1SDimitry Andric   }
988*0fca6ea1SDimitry Andric 
989*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
990*0fca6ea1SDimitry Andric     return OperandPredicateMatcher::isIdentical(B) &&
991*0fca6ea1SDimitry Andric            SizeInBits == cast<PointerToAnyOperandMatcher>(&B)->SizeInBits;
992*0fca6ea1SDimitry Andric   }
993*0fca6ea1SDimitry Andric 
994*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
995*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
996*0fca6ea1SDimitry Andric };
997*0fca6ea1SDimitry Andric 
998*0fca6ea1SDimitry Andric /// Generates code to record named operand in RecordedOperands list at StoreIdx.
999*0fca6ea1SDimitry Andric /// Predicates with 'let PredicateCodeUsesOperands = 1' get RecordedOperands as
1000*0fca6ea1SDimitry Andric /// an argument to predicate's c++ code once all operands have been matched.
1001*0fca6ea1SDimitry Andric class RecordNamedOperandMatcher : public OperandPredicateMatcher {
1002*0fca6ea1SDimitry Andric protected:
1003*0fca6ea1SDimitry Andric   unsigned StoreIdx;
1004*0fca6ea1SDimitry Andric   std::string Name;
1005*0fca6ea1SDimitry Andric 
1006*0fca6ea1SDimitry Andric public:
1007*0fca6ea1SDimitry Andric   RecordNamedOperandMatcher(unsigned InsnVarID, unsigned OpIdx,
1008*0fca6ea1SDimitry Andric                             unsigned StoreIdx, StringRef Name)
1009*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(OPM_RecordNamedOperand, InsnVarID, OpIdx),
1010*0fca6ea1SDimitry Andric         StoreIdx(StoreIdx), Name(Name) {}
1011*0fca6ea1SDimitry Andric 
1012*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1013*0fca6ea1SDimitry Andric     return P->getKind() == OPM_RecordNamedOperand;
1014*0fca6ea1SDimitry Andric   }
1015*0fca6ea1SDimitry Andric 
1016*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
1017*0fca6ea1SDimitry Andric     return OperandPredicateMatcher::isIdentical(B) &&
1018*0fca6ea1SDimitry Andric            StoreIdx == cast<RecordNamedOperandMatcher>(&B)->StoreIdx &&
1019*0fca6ea1SDimitry Andric            Name == cast<RecordNamedOperandMatcher>(&B)->Name;
1020*0fca6ea1SDimitry Andric   }
1021*0fca6ea1SDimitry Andric 
1022*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1023*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1024*0fca6ea1SDimitry Andric };
1025*0fca6ea1SDimitry Andric 
1026*0fca6ea1SDimitry Andric /// Generates code to store a register operand's type into the set of temporary
1027*0fca6ea1SDimitry Andric /// LLTs.
1028*0fca6ea1SDimitry Andric class RecordRegisterType : public OperandPredicateMatcher {
1029*0fca6ea1SDimitry Andric protected:
1030*0fca6ea1SDimitry Andric   TempTypeIdx Idx;
1031*0fca6ea1SDimitry Andric 
1032*0fca6ea1SDimitry Andric public:
1033*0fca6ea1SDimitry Andric   RecordRegisterType(unsigned InsnVarID, unsigned OpIdx, TempTypeIdx Idx)
1034*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(OPM_RecordRegType, InsnVarID, OpIdx), Idx(Idx) {
1035*0fca6ea1SDimitry Andric   }
1036*0fca6ea1SDimitry Andric 
1037*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1038*0fca6ea1SDimitry Andric     return P->getKind() == OPM_RecordRegType;
1039*0fca6ea1SDimitry Andric   }
1040*0fca6ea1SDimitry Andric 
1041*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
1042*0fca6ea1SDimitry Andric     return OperandPredicateMatcher::isIdentical(B) &&
1043*0fca6ea1SDimitry Andric            Idx == cast<RecordRegisterType>(&B)->Idx;
1044*0fca6ea1SDimitry Andric   }
1045*0fca6ea1SDimitry Andric 
1046*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1047*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1048*0fca6ea1SDimitry Andric };
1049*0fca6ea1SDimitry Andric 
1050*0fca6ea1SDimitry Andric /// Generates code to check that an operand is a particular target constant.
1051*0fca6ea1SDimitry Andric class ComplexPatternOperandMatcher : public OperandPredicateMatcher {
1052*0fca6ea1SDimitry Andric protected:
1053*0fca6ea1SDimitry Andric   const OperandMatcher &Operand;
1054*0fca6ea1SDimitry Andric   const Record &TheDef;
1055*0fca6ea1SDimitry Andric 
1056*0fca6ea1SDimitry Andric   unsigned getAllocatedTemporariesBaseID() const;
1057*0fca6ea1SDimitry Andric 
1058*0fca6ea1SDimitry Andric public:
1059*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override { return false; }
1060*0fca6ea1SDimitry Andric 
1061*0fca6ea1SDimitry Andric   ComplexPatternOperandMatcher(unsigned InsnVarID, unsigned OpIdx,
1062*0fca6ea1SDimitry Andric                                const OperandMatcher &Operand,
1063*0fca6ea1SDimitry Andric                                const Record &TheDef)
1064*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(OPM_ComplexPattern, InsnVarID, OpIdx),
1065*0fca6ea1SDimitry Andric         Operand(Operand), TheDef(TheDef) {}
1066*0fca6ea1SDimitry Andric 
1067*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1068*0fca6ea1SDimitry Andric     return P->getKind() == OPM_ComplexPattern;
1069*0fca6ea1SDimitry Andric   }
1070*0fca6ea1SDimitry Andric 
1071*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1072*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1073*0fca6ea1SDimitry Andric   unsigned countRendererFns() const override { return 1; }
1074*0fca6ea1SDimitry Andric };
1075*0fca6ea1SDimitry Andric 
1076*0fca6ea1SDimitry Andric /// Generates code to check that an operand is in a particular register bank.
1077*0fca6ea1SDimitry Andric class RegisterBankOperandMatcher : public OperandPredicateMatcher {
1078*0fca6ea1SDimitry Andric protected:
1079*0fca6ea1SDimitry Andric   const CodeGenRegisterClass &RC;
1080*0fca6ea1SDimitry Andric 
1081*0fca6ea1SDimitry Andric public:
1082*0fca6ea1SDimitry Andric   RegisterBankOperandMatcher(unsigned InsnVarID, unsigned OpIdx,
1083*0fca6ea1SDimitry Andric                              const CodeGenRegisterClass &RC)
1084*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(OPM_RegBank, InsnVarID, OpIdx), RC(RC) {}
1085*0fca6ea1SDimitry Andric 
1086*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override;
1087*0fca6ea1SDimitry Andric 
1088*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1089*0fca6ea1SDimitry Andric     return P->getKind() == OPM_RegBank;
1090*0fca6ea1SDimitry Andric   }
1091*0fca6ea1SDimitry Andric 
1092*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1093*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1094*0fca6ea1SDimitry Andric };
1095*0fca6ea1SDimitry Andric 
1096*0fca6ea1SDimitry Andric /// Generates code to check that an operand is a basic block.
1097*0fca6ea1SDimitry Andric class MBBOperandMatcher : public OperandPredicateMatcher {
1098*0fca6ea1SDimitry Andric public:
1099*0fca6ea1SDimitry Andric   MBBOperandMatcher(unsigned InsnVarID, unsigned OpIdx)
1100*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(OPM_MBB, InsnVarID, OpIdx) {}
1101*0fca6ea1SDimitry Andric 
1102*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1103*0fca6ea1SDimitry Andric     return P->getKind() == OPM_MBB;
1104*0fca6ea1SDimitry Andric   }
1105*0fca6ea1SDimitry Andric 
1106*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1107*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1108*0fca6ea1SDimitry Andric };
1109*0fca6ea1SDimitry Andric 
1110*0fca6ea1SDimitry Andric class ImmOperandMatcher : public OperandPredicateMatcher {
1111*0fca6ea1SDimitry Andric public:
1112*0fca6ea1SDimitry Andric   ImmOperandMatcher(unsigned InsnVarID, unsigned OpIdx)
1113*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(IPM_Imm, InsnVarID, OpIdx) {}
1114*0fca6ea1SDimitry Andric 
1115*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1116*0fca6ea1SDimitry Andric     return P->getKind() == IPM_Imm;
1117*0fca6ea1SDimitry Andric   }
1118*0fca6ea1SDimitry Andric 
1119*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1120*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1121*0fca6ea1SDimitry Andric };
1122*0fca6ea1SDimitry Andric 
1123*0fca6ea1SDimitry Andric /// Generates code to check that an operand is a G_CONSTANT with a particular
1124*0fca6ea1SDimitry Andric /// int.
1125*0fca6ea1SDimitry Andric class ConstantIntOperandMatcher : public OperandPredicateMatcher {
1126*0fca6ea1SDimitry Andric protected:
1127*0fca6ea1SDimitry Andric   int64_t Value;
1128*0fca6ea1SDimitry Andric 
1129*0fca6ea1SDimitry Andric public:
1130*0fca6ea1SDimitry Andric   ConstantIntOperandMatcher(unsigned InsnVarID, unsigned OpIdx, int64_t Value)
1131*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(OPM_Int, InsnVarID, OpIdx), Value(Value) {}
1132*0fca6ea1SDimitry Andric 
1133*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
1134*0fca6ea1SDimitry Andric     return OperandPredicateMatcher::isIdentical(B) &&
1135*0fca6ea1SDimitry Andric            Value == cast<ConstantIntOperandMatcher>(&B)->Value;
1136*0fca6ea1SDimitry Andric   }
1137*0fca6ea1SDimitry Andric 
1138*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1139*0fca6ea1SDimitry Andric     return P->getKind() == OPM_Int;
1140*0fca6ea1SDimitry Andric   }
1141*0fca6ea1SDimitry Andric 
1142*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1143*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1144*0fca6ea1SDimitry Andric };
1145*0fca6ea1SDimitry Andric 
1146*0fca6ea1SDimitry Andric /// Generates code to check that an operand is a raw int (where MO.isImm() or
1147*0fca6ea1SDimitry Andric /// MO.isCImm() is true).
1148*0fca6ea1SDimitry Andric class LiteralIntOperandMatcher : public OperandPredicateMatcher {
1149*0fca6ea1SDimitry Andric protected:
1150*0fca6ea1SDimitry Andric   int64_t Value;
1151*0fca6ea1SDimitry Andric 
1152*0fca6ea1SDimitry Andric public:
1153*0fca6ea1SDimitry Andric   LiteralIntOperandMatcher(unsigned InsnVarID, unsigned OpIdx, int64_t Value)
1154*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(OPM_LiteralInt, InsnVarID, OpIdx),
1155*0fca6ea1SDimitry Andric         Value(Value) {}
1156*0fca6ea1SDimitry Andric 
1157*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
1158*0fca6ea1SDimitry Andric     return OperandPredicateMatcher::isIdentical(B) &&
1159*0fca6ea1SDimitry Andric            Value == cast<LiteralIntOperandMatcher>(&B)->Value;
1160*0fca6ea1SDimitry Andric   }
1161*0fca6ea1SDimitry Andric 
1162*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1163*0fca6ea1SDimitry Andric     return P->getKind() == OPM_LiteralInt;
1164*0fca6ea1SDimitry Andric   }
1165*0fca6ea1SDimitry Andric 
1166*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1167*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1168*0fca6ea1SDimitry Andric };
1169*0fca6ea1SDimitry Andric 
1170*0fca6ea1SDimitry Andric /// Generates code to check that an operand is an CmpInst predicate
1171*0fca6ea1SDimitry Andric class CmpPredicateOperandMatcher : public OperandPredicateMatcher {
1172*0fca6ea1SDimitry Andric protected:
1173*0fca6ea1SDimitry Andric   std::string PredName;
1174*0fca6ea1SDimitry Andric 
1175*0fca6ea1SDimitry Andric public:
1176*0fca6ea1SDimitry Andric   CmpPredicateOperandMatcher(unsigned InsnVarID, unsigned OpIdx, std::string P)
1177*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(OPM_CmpPredicate, InsnVarID, OpIdx),
1178*0fca6ea1SDimitry Andric         PredName(std::move(P)) {}
1179*0fca6ea1SDimitry Andric 
1180*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
1181*0fca6ea1SDimitry Andric     return OperandPredicateMatcher::isIdentical(B) &&
1182*0fca6ea1SDimitry Andric            PredName == cast<CmpPredicateOperandMatcher>(&B)->PredName;
1183*0fca6ea1SDimitry Andric   }
1184*0fca6ea1SDimitry Andric 
1185*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1186*0fca6ea1SDimitry Andric     return P->getKind() == OPM_CmpPredicate;
1187*0fca6ea1SDimitry Andric   }
1188*0fca6ea1SDimitry Andric 
1189*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1190*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1191*0fca6ea1SDimitry Andric };
1192*0fca6ea1SDimitry Andric 
1193*0fca6ea1SDimitry Andric /// Generates code to check that an operand is an intrinsic ID.
1194*0fca6ea1SDimitry Andric class IntrinsicIDOperandMatcher : public OperandPredicateMatcher {
1195*0fca6ea1SDimitry Andric protected:
1196*0fca6ea1SDimitry Andric   const CodeGenIntrinsic *II;
1197*0fca6ea1SDimitry Andric 
1198*0fca6ea1SDimitry Andric public:
1199*0fca6ea1SDimitry Andric   IntrinsicIDOperandMatcher(unsigned InsnVarID, unsigned OpIdx,
1200*0fca6ea1SDimitry Andric                             const CodeGenIntrinsic *II)
1201*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(OPM_IntrinsicID, InsnVarID, OpIdx), II(II) {}
1202*0fca6ea1SDimitry Andric 
1203*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
1204*0fca6ea1SDimitry Andric     return OperandPredicateMatcher::isIdentical(B) &&
1205*0fca6ea1SDimitry Andric            II == cast<IntrinsicIDOperandMatcher>(&B)->II;
1206*0fca6ea1SDimitry Andric   }
1207*0fca6ea1SDimitry Andric 
1208*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1209*0fca6ea1SDimitry Andric     return P->getKind() == OPM_IntrinsicID;
1210*0fca6ea1SDimitry Andric   }
1211*0fca6ea1SDimitry Andric 
1212*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1213*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1214*0fca6ea1SDimitry Andric };
1215*0fca6ea1SDimitry Andric 
1216*0fca6ea1SDimitry Andric /// Generates code to check that this operand is an immediate whose value meets
1217*0fca6ea1SDimitry Andric /// an immediate predicate.
1218*0fca6ea1SDimitry Andric class OperandImmPredicateMatcher : public OperandPredicateMatcher {
1219*0fca6ea1SDimitry Andric protected:
1220*0fca6ea1SDimitry Andric   TreePredicateFn Predicate;
1221*0fca6ea1SDimitry Andric 
1222*0fca6ea1SDimitry Andric public:
1223*0fca6ea1SDimitry Andric   OperandImmPredicateMatcher(unsigned InsnVarID, unsigned OpIdx,
1224*0fca6ea1SDimitry Andric                              const TreePredicateFn &Predicate)
1225*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(IPM_ImmPredicate, InsnVarID, OpIdx),
1226*0fca6ea1SDimitry Andric         Predicate(Predicate) {}
1227*0fca6ea1SDimitry Andric 
1228*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
1229*0fca6ea1SDimitry Andric     return OperandPredicateMatcher::isIdentical(B) &&
1230*0fca6ea1SDimitry Andric            Predicate.getOrigPatFragRecord() ==
1231*0fca6ea1SDimitry Andric                cast<OperandImmPredicateMatcher>(&B)
1232*0fca6ea1SDimitry Andric                    ->Predicate.getOrigPatFragRecord();
1233*0fca6ea1SDimitry Andric   }
1234*0fca6ea1SDimitry Andric 
1235*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1236*0fca6ea1SDimitry Andric     return P->getKind() == IPM_ImmPredicate;
1237*0fca6ea1SDimitry Andric   }
1238*0fca6ea1SDimitry Andric 
1239*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1240*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1241*0fca6ea1SDimitry Andric };
1242*0fca6ea1SDimitry Andric 
1243*0fca6ea1SDimitry Andric /// Generates code to check that a set of predicates match for a particular
1244*0fca6ea1SDimitry Andric /// operand.
1245*0fca6ea1SDimitry Andric class OperandMatcher : public PredicateListMatcher<OperandPredicateMatcher> {
1246*0fca6ea1SDimitry Andric protected:
1247*0fca6ea1SDimitry Andric   InstructionMatcher &Insn;
1248*0fca6ea1SDimitry Andric   unsigned OpIdx;
1249*0fca6ea1SDimitry Andric   std::string SymbolicName;
1250*0fca6ea1SDimitry Andric 
1251*0fca6ea1SDimitry Andric   /// The index of the first temporary variable allocated to this operand. The
1252*0fca6ea1SDimitry Andric   /// number of allocated temporaries can be found with
1253*0fca6ea1SDimitry Andric   /// countRendererFns().
1254*0fca6ea1SDimitry Andric   unsigned AllocatedTemporariesBaseID;
1255*0fca6ea1SDimitry Andric 
1256*0fca6ea1SDimitry Andric   TempTypeIdx TTIdx = 0;
1257*0fca6ea1SDimitry Andric 
1258*0fca6ea1SDimitry Andric public:
1259*0fca6ea1SDimitry Andric   OperandMatcher(InstructionMatcher &Insn, unsigned OpIdx,
1260*0fca6ea1SDimitry Andric                  const std::string &SymbolicName,
1261*0fca6ea1SDimitry Andric                  unsigned AllocatedTemporariesBaseID)
1262*0fca6ea1SDimitry Andric       : Insn(Insn), OpIdx(OpIdx), SymbolicName(SymbolicName),
1263*0fca6ea1SDimitry Andric         AllocatedTemporariesBaseID(AllocatedTemporariesBaseID) {}
1264*0fca6ea1SDimitry Andric 
1265*0fca6ea1SDimitry Andric   bool hasSymbolicName() const { return !SymbolicName.empty(); }
1266*0fca6ea1SDimitry Andric   StringRef getSymbolicName() const { return SymbolicName; }
1267*0fca6ea1SDimitry Andric   void setSymbolicName(StringRef Name) {
1268*0fca6ea1SDimitry Andric     assert(SymbolicName.empty() && "Operand already has a symbolic name");
1269*0fca6ea1SDimitry Andric     SymbolicName = std::string(Name);
1270*0fca6ea1SDimitry Andric   }
1271*0fca6ea1SDimitry Andric 
1272*0fca6ea1SDimitry Andric   /// Construct a new operand predicate and add it to the matcher.
1273*0fca6ea1SDimitry Andric   template <class Kind, class... Args>
1274*0fca6ea1SDimitry Andric   std::optional<Kind *> addPredicate(Args &&...args) {
1275*0fca6ea1SDimitry Andric     if (isSameAsAnotherOperand())
1276*0fca6ea1SDimitry Andric       return std::nullopt;
1277*0fca6ea1SDimitry Andric     Predicates.emplace_back(std::make_unique<Kind>(
1278*0fca6ea1SDimitry Andric         getInsnVarID(), getOpIdx(), std::forward<Args>(args)...));
1279*0fca6ea1SDimitry Andric     return static_cast<Kind *>(Predicates.back().get());
1280*0fca6ea1SDimitry Andric   }
1281*0fca6ea1SDimitry Andric 
1282*0fca6ea1SDimitry Andric   unsigned getOpIdx() const { return OpIdx; }
1283*0fca6ea1SDimitry Andric   unsigned getInsnVarID() const;
1284*0fca6ea1SDimitry Andric 
1285*0fca6ea1SDimitry Andric   /// If this OperandMatcher has not been assigned a TempTypeIdx yet, assigns it
1286*0fca6ea1SDimitry Andric   /// one and adds a `RecordRegisterType` predicate to this matcher. If one has
1287*0fca6ea1SDimitry Andric   /// already been assigned, simply returns it.
1288*0fca6ea1SDimitry Andric   TempTypeIdx getTempTypeIdx(RuleMatcher &Rule);
1289*0fca6ea1SDimitry Andric 
1290*0fca6ea1SDimitry Andric   std::string getOperandExpr(unsigned InsnVarID) const;
1291*0fca6ea1SDimitry Andric 
1292*0fca6ea1SDimitry Andric   InstructionMatcher &getInstructionMatcher() const { return Insn; }
1293*0fca6ea1SDimitry Andric 
1294*0fca6ea1SDimitry Andric   Error addTypeCheckPredicate(const TypeSetByHwMode &VTy,
1295*0fca6ea1SDimitry Andric                               bool OperandIsAPointer);
1296*0fca6ea1SDimitry Andric 
1297*0fca6ea1SDimitry Andric   /// Emit MatchTable opcodes that test whether the instruction named in
1298*0fca6ea1SDimitry Andric   /// InsnVarID matches all the predicates and all the operands.
1299*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule);
1300*0fca6ea1SDimitry Andric 
1301*0fca6ea1SDimitry Andric   /// Compare the priority of this object and B.
1302*0fca6ea1SDimitry Andric   ///
1303*0fca6ea1SDimitry Andric   /// Returns true if this object is more important than B.
1304*0fca6ea1SDimitry Andric   bool isHigherPriorityThan(OperandMatcher &B);
1305*0fca6ea1SDimitry Andric 
1306*0fca6ea1SDimitry Andric   /// Report the maximum number of temporary operands needed by the operand
1307*0fca6ea1SDimitry Andric   /// matcher.
1308*0fca6ea1SDimitry Andric   unsigned countRendererFns();
1309*0fca6ea1SDimitry Andric 
1310*0fca6ea1SDimitry Andric   unsigned getAllocatedTemporariesBaseID() const {
1311*0fca6ea1SDimitry Andric     return AllocatedTemporariesBaseID;
1312*0fca6ea1SDimitry Andric   }
1313*0fca6ea1SDimitry Andric 
1314*0fca6ea1SDimitry Andric   bool isSameAsAnotherOperand() {
1315*0fca6ea1SDimitry Andric     for (const auto &Predicate : predicates())
1316*0fca6ea1SDimitry Andric       if (isa<SameOperandMatcher>(Predicate))
1317*0fca6ea1SDimitry Andric         return true;
1318*0fca6ea1SDimitry Andric     return false;
1319*0fca6ea1SDimitry Andric   }
1320*0fca6ea1SDimitry Andric };
1321*0fca6ea1SDimitry Andric 
1322*0fca6ea1SDimitry Andric /// Generates code to check a predicate on an instruction.
1323*0fca6ea1SDimitry Andric ///
1324*0fca6ea1SDimitry Andric /// Typical predicates include:
1325*0fca6ea1SDimitry Andric /// * The opcode of the instruction is a particular value.
1326*0fca6ea1SDimitry Andric /// * The nsw/nuw flag is/isn't set.
1327*0fca6ea1SDimitry Andric class InstructionPredicateMatcher : public PredicateMatcher {
1328*0fca6ea1SDimitry Andric public:
1329*0fca6ea1SDimitry Andric   InstructionPredicateMatcher(PredicateKind Kind, unsigned InsnVarID)
1330*0fca6ea1SDimitry Andric       : PredicateMatcher(Kind, InsnVarID) {}
1331*0fca6ea1SDimitry Andric   virtual ~InstructionPredicateMatcher() {}
1332*0fca6ea1SDimitry Andric 
1333*0fca6ea1SDimitry Andric   /// Compare the priority of this object and B.
1334*0fca6ea1SDimitry Andric   ///
1335*0fca6ea1SDimitry Andric   /// Returns true if this object is more important than B.
1336*0fca6ea1SDimitry Andric   virtual bool
1337*0fca6ea1SDimitry Andric   isHigherPriorityThan(const InstructionPredicateMatcher &B) const {
1338*0fca6ea1SDimitry Andric     return Kind < B.Kind;
1339*0fca6ea1SDimitry Andric   };
1340*0fca6ea1SDimitry Andric };
1341*0fca6ea1SDimitry Andric 
1342*0fca6ea1SDimitry Andric template <>
1343*0fca6ea1SDimitry Andric inline std::string
1344*0fca6ea1SDimitry Andric PredicateListMatcher<PredicateMatcher>::getNoPredicateComment() const {
1345*0fca6ea1SDimitry Andric   return "No instruction predicates";
1346*0fca6ea1SDimitry Andric }
1347*0fca6ea1SDimitry Andric 
1348*0fca6ea1SDimitry Andric /// Generates code to check the opcode of an instruction.
1349*0fca6ea1SDimitry Andric class InstructionOpcodeMatcher : public InstructionPredicateMatcher {
1350*0fca6ea1SDimitry Andric protected:
1351*0fca6ea1SDimitry Andric   // Allow matching one to several, similar opcodes that share properties. This
1352*0fca6ea1SDimitry Andric   // is to handle patterns where one SelectionDAG operation maps to multiple
1353*0fca6ea1SDimitry Andric   // GlobalISel ones (e.g. G_BUILD_VECTOR and G_BUILD_VECTOR_TRUNC). The first
1354*0fca6ea1SDimitry Andric   // is treated as the canonical opcode.
1355*0fca6ea1SDimitry Andric   SmallVector<const CodeGenInstruction *, 2> Insts;
1356*0fca6ea1SDimitry Andric 
1357*0fca6ea1SDimitry Andric   static DenseMap<const CodeGenInstruction *, unsigned> OpcodeValues;
1358*0fca6ea1SDimitry Andric 
1359*0fca6ea1SDimitry Andric   MatchTableRecord getInstValue(const CodeGenInstruction *I) const;
1360*0fca6ea1SDimitry Andric 
1361*0fca6ea1SDimitry Andric public:
1362*0fca6ea1SDimitry Andric   static void initOpcodeValuesMap(const CodeGenTarget &Target);
1363*0fca6ea1SDimitry Andric 
1364*0fca6ea1SDimitry Andric   InstructionOpcodeMatcher(unsigned InsnVarID,
1365*0fca6ea1SDimitry Andric                            ArrayRef<const CodeGenInstruction *> I)
1366*0fca6ea1SDimitry Andric       : InstructionPredicateMatcher(IPM_Opcode, InsnVarID),
1367*0fca6ea1SDimitry Andric         Insts(I.begin(), I.end()) {
1368*0fca6ea1SDimitry Andric     assert((Insts.size() == 1 || Insts.size() == 2) &&
1369*0fca6ea1SDimitry Andric            "unexpected number of opcode alternatives");
1370*0fca6ea1SDimitry Andric   }
1371*0fca6ea1SDimitry Andric 
1372*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1373*0fca6ea1SDimitry Andric     return P->getKind() == IPM_Opcode;
1374*0fca6ea1SDimitry Andric   }
1375*0fca6ea1SDimitry Andric 
1376*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
1377*0fca6ea1SDimitry Andric     return InstructionPredicateMatcher::isIdentical(B) &&
1378*0fca6ea1SDimitry Andric            Insts == cast<InstructionOpcodeMatcher>(&B)->Insts;
1379*0fca6ea1SDimitry Andric   }
1380*0fca6ea1SDimitry Andric 
1381*0fca6ea1SDimitry Andric   bool hasValue() const override {
1382*0fca6ea1SDimitry Andric     return Insts.size() == 1 && OpcodeValues.count(Insts[0]);
1383*0fca6ea1SDimitry Andric   }
1384*0fca6ea1SDimitry Andric 
1385*0fca6ea1SDimitry Andric   // TODO: This is used for the SwitchMatcher optimization. We should be able to
1386*0fca6ea1SDimitry Andric   // return a list of the opcodes to match.
1387*0fca6ea1SDimitry Andric   MatchTableRecord getValue() const override;
1388*0fca6ea1SDimitry Andric 
1389*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1390*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1391*0fca6ea1SDimitry Andric 
1392*0fca6ea1SDimitry Andric   /// Compare the priority of this object and B.
1393*0fca6ea1SDimitry Andric   ///
1394*0fca6ea1SDimitry Andric   /// Returns true if this object is more important than B.
1395*0fca6ea1SDimitry Andric   bool
1396*0fca6ea1SDimitry Andric   isHigherPriorityThan(const InstructionPredicateMatcher &B) const override;
1397*0fca6ea1SDimitry Andric 
1398*0fca6ea1SDimitry Andric   bool isConstantInstruction() const;
1399*0fca6ea1SDimitry Andric 
1400*0fca6ea1SDimitry Andric   // The first opcode is the canonical opcode, and later are alternatives.
1401*0fca6ea1SDimitry Andric   StringRef getOpcode() const;
1402*0fca6ea1SDimitry Andric   ArrayRef<const CodeGenInstruction *> getAlternativeOpcodes() { return Insts; }
1403*0fca6ea1SDimitry Andric   bool isVariadicNumOperands() const;
1404*0fca6ea1SDimitry Andric   StringRef getOperandType(unsigned OpIdx) const;
1405*0fca6ea1SDimitry Andric };
1406*0fca6ea1SDimitry Andric 
1407*0fca6ea1SDimitry Andric class InstructionNumOperandsMatcher final : public InstructionPredicateMatcher {
1408*0fca6ea1SDimitry Andric   unsigned NumOperands = 0;
1409*0fca6ea1SDimitry Andric 
1410*0fca6ea1SDimitry Andric public:
1411*0fca6ea1SDimitry Andric   InstructionNumOperandsMatcher(unsigned InsnVarID, unsigned NumOperands)
1412*0fca6ea1SDimitry Andric       : InstructionPredicateMatcher(IPM_NumOperands, InsnVarID),
1413*0fca6ea1SDimitry Andric         NumOperands(NumOperands) {}
1414*0fca6ea1SDimitry Andric 
1415*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1416*0fca6ea1SDimitry Andric     return P->getKind() == IPM_NumOperands;
1417*0fca6ea1SDimitry Andric   }
1418*0fca6ea1SDimitry Andric 
1419*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
1420*0fca6ea1SDimitry Andric     return InstructionPredicateMatcher::isIdentical(B) &&
1421*0fca6ea1SDimitry Andric            NumOperands == cast<InstructionNumOperandsMatcher>(&B)->NumOperands;
1422*0fca6ea1SDimitry Andric   }
1423*0fca6ea1SDimitry Andric 
1424*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1425*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1426*0fca6ea1SDimitry Andric };
1427*0fca6ea1SDimitry Andric 
1428*0fca6ea1SDimitry Andric /// Generates code to check that this instruction is a constant whose value
1429*0fca6ea1SDimitry Andric /// meets an immediate predicate.
1430*0fca6ea1SDimitry Andric ///
1431*0fca6ea1SDimitry Andric /// Immediates are slightly odd since they are typically used like an operand
1432*0fca6ea1SDimitry Andric /// but are represented as an operator internally. We typically write simm8:$src
1433*0fca6ea1SDimitry Andric /// in a tablegen pattern, but this is just syntactic sugar for
1434*0fca6ea1SDimitry Andric /// (imm:i32)<<P:Predicate_simm8>>:$imm which more directly describes the nodes
1435*0fca6ea1SDimitry Andric /// that will be matched and the predicate (which is attached to the imm
1436*0fca6ea1SDimitry Andric /// operator) that will be tested. In SelectionDAG this describes a
1437*0fca6ea1SDimitry Andric /// ConstantSDNode whose internal value will be tested using the simm8
1438*0fca6ea1SDimitry Andric /// predicate.
1439*0fca6ea1SDimitry Andric ///
1440*0fca6ea1SDimitry Andric /// The corresponding GlobalISel representation is %1 = G_CONSTANT iN Value. In
1441*0fca6ea1SDimitry Andric /// this representation, the immediate could be tested with an
1442*0fca6ea1SDimitry Andric /// InstructionMatcher, InstructionOpcodeMatcher, OperandMatcher, and a
1443*0fca6ea1SDimitry Andric /// OperandPredicateMatcher-subclass to check the Value meets the predicate but
1444*0fca6ea1SDimitry Andric /// there are two implementation issues with producing that matcher
1445*0fca6ea1SDimitry Andric /// configuration from the SelectionDAG pattern:
1446*0fca6ea1SDimitry Andric /// * ImmLeaf is a PatFrag whose root is an InstructionMatcher. This means that
1447*0fca6ea1SDimitry Andric ///   were we to sink the immediate predicate to the operand we would have to
1448*0fca6ea1SDimitry Andric ///   have two partial implementations of PatFrag support, one for immediates
1449*0fca6ea1SDimitry Andric ///   and one for non-immediates.
1450*0fca6ea1SDimitry Andric /// * At the point we handle the predicate, the OperandMatcher hasn't been
1451*0fca6ea1SDimitry Andric ///   created yet. If we were to sink the predicate to the OperandMatcher we
1452*0fca6ea1SDimitry Andric ///   would also have to complicate (or duplicate) the code that descends and
1453*0fca6ea1SDimitry Andric ///   creates matchers for the subtree.
1454*0fca6ea1SDimitry Andric /// Overall, it's simpler to handle it in the place it was found.
1455*0fca6ea1SDimitry Andric class InstructionImmPredicateMatcher : public InstructionPredicateMatcher {
1456*0fca6ea1SDimitry Andric protected:
1457*0fca6ea1SDimitry Andric   TreePredicateFn Predicate;
1458*0fca6ea1SDimitry Andric 
1459*0fca6ea1SDimitry Andric public:
1460*0fca6ea1SDimitry Andric   InstructionImmPredicateMatcher(unsigned InsnVarID,
1461*0fca6ea1SDimitry Andric                                  const TreePredicateFn &Predicate)
1462*0fca6ea1SDimitry Andric       : InstructionPredicateMatcher(IPM_ImmPredicate, InsnVarID),
1463*0fca6ea1SDimitry Andric         Predicate(Predicate) {}
1464*0fca6ea1SDimitry Andric 
1465*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override;
1466*0fca6ea1SDimitry Andric 
1467*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1468*0fca6ea1SDimitry Andric     return P->getKind() == IPM_ImmPredicate;
1469*0fca6ea1SDimitry Andric   }
1470*0fca6ea1SDimitry Andric 
1471*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1472*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1473*0fca6ea1SDimitry Andric };
1474*0fca6ea1SDimitry Andric 
1475*0fca6ea1SDimitry Andric /// Generates code to check that a memory instruction has a atomic ordering
1476*0fca6ea1SDimitry Andric /// MachineMemoryOperand.
1477*0fca6ea1SDimitry Andric class AtomicOrderingMMOPredicateMatcher : public InstructionPredicateMatcher {
1478*0fca6ea1SDimitry Andric public:
1479*0fca6ea1SDimitry Andric   enum AOComparator {
1480*0fca6ea1SDimitry Andric     AO_Exactly,
1481*0fca6ea1SDimitry Andric     AO_OrStronger,
1482*0fca6ea1SDimitry Andric     AO_WeakerThan,
1483*0fca6ea1SDimitry Andric   };
1484*0fca6ea1SDimitry Andric 
1485*0fca6ea1SDimitry Andric protected:
1486*0fca6ea1SDimitry Andric   StringRef Order;
1487*0fca6ea1SDimitry Andric   AOComparator Comparator;
1488*0fca6ea1SDimitry Andric 
1489*0fca6ea1SDimitry Andric public:
1490*0fca6ea1SDimitry Andric   AtomicOrderingMMOPredicateMatcher(unsigned InsnVarID, StringRef Order,
1491*0fca6ea1SDimitry Andric                                     AOComparator Comparator = AO_Exactly)
1492*0fca6ea1SDimitry Andric       : InstructionPredicateMatcher(IPM_AtomicOrderingMMO, InsnVarID),
1493*0fca6ea1SDimitry Andric         Order(Order), Comparator(Comparator) {}
1494*0fca6ea1SDimitry Andric 
1495*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1496*0fca6ea1SDimitry Andric     return P->getKind() == IPM_AtomicOrderingMMO;
1497*0fca6ea1SDimitry Andric   }
1498*0fca6ea1SDimitry Andric 
1499*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override;
1500*0fca6ea1SDimitry Andric 
1501*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1502*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1503*0fca6ea1SDimitry Andric };
1504*0fca6ea1SDimitry Andric 
1505*0fca6ea1SDimitry Andric /// Generates code to check that the size of an MMO is exactly N bytes.
1506*0fca6ea1SDimitry Andric class MemorySizePredicateMatcher : public InstructionPredicateMatcher {
1507*0fca6ea1SDimitry Andric protected:
1508*0fca6ea1SDimitry Andric   unsigned MMOIdx;
1509*0fca6ea1SDimitry Andric   uint64_t Size;
1510*0fca6ea1SDimitry Andric 
1511*0fca6ea1SDimitry Andric public:
1512*0fca6ea1SDimitry Andric   MemorySizePredicateMatcher(unsigned InsnVarID, unsigned MMOIdx, unsigned Size)
1513*0fca6ea1SDimitry Andric       : InstructionPredicateMatcher(IPM_MemoryLLTSize, InsnVarID),
1514*0fca6ea1SDimitry Andric         MMOIdx(MMOIdx), Size(Size) {}
1515*0fca6ea1SDimitry Andric 
1516*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1517*0fca6ea1SDimitry Andric     return P->getKind() == IPM_MemoryLLTSize;
1518*0fca6ea1SDimitry Andric   }
1519*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
1520*0fca6ea1SDimitry Andric     return InstructionPredicateMatcher::isIdentical(B) &&
1521*0fca6ea1SDimitry Andric            MMOIdx == cast<MemorySizePredicateMatcher>(&B)->MMOIdx &&
1522*0fca6ea1SDimitry Andric            Size == cast<MemorySizePredicateMatcher>(&B)->Size;
1523*0fca6ea1SDimitry Andric   }
1524*0fca6ea1SDimitry Andric 
1525*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1526*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1527*0fca6ea1SDimitry Andric };
1528*0fca6ea1SDimitry Andric 
1529*0fca6ea1SDimitry Andric class MemoryAddressSpacePredicateMatcher : public InstructionPredicateMatcher {
1530*0fca6ea1SDimitry Andric protected:
1531*0fca6ea1SDimitry Andric   unsigned MMOIdx;
1532*0fca6ea1SDimitry Andric   SmallVector<unsigned, 4> AddrSpaces;
1533*0fca6ea1SDimitry Andric 
1534*0fca6ea1SDimitry Andric public:
1535*0fca6ea1SDimitry Andric   MemoryAddressSpacePredicateMatcher(unsigned InsnVarID, unsigned MMOIdx,
1536*0fca6ea1SDimitry Andric                                      ArrayRef<unsigned> AddrSpaces)
1537*0fca6ea1SDimitry Andric       : InstructionPredicateMatcher(IPM_MemoryAddressSpace, InsnVarID),
1538*0fca6ea1SDimitry Andric         MMOIdx(MMOIdx), AddrSpaces(AddrSpaces.begin(), AddrSpaces.end()) {}
1539*0fca6ea1SDimitry Andric 
1540*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1541*0fca6ea1SDimitry Andric     return P->getKind() == IPM_MemoryAddressSpace;
1542*0fca6ea1SDimitry Andric   }
1543*0fca6ea1SDimitry Andric 
1544*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override;
1545*0fca6ea1SDimitry Andric 
1546*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1547*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1548*0fca6ea1SDimitry Andric };
1549*0fca6ea1SDimitry Andric 
1550*0fca6ea1SDimitry Andric class MemoryAlignmentPredicateMatcher : public InstructionPredicateMatcher {
1551*0fca6ea1SDimitry Andric protected:
1552*0fca6ea1SDimitry Andric   unsigned MMOIdx;
1553*0fca6ea1SDimitry Andric   int MinAlign;
1554*0fca6ea1SDimitry Andric 
1555*0fca6ea1SDimitry Andric public:
1556*0fca6ea1SDimitry Andric   MemoryAlignmentPredicateMatcher(unsigned InsnVarID, unsigned MMOIdx,
1557*0fca6ea1SDimitry Andric                                   int MinAlign)
1558*0fca6ea1SDimitry Andric       : InstructionPredicateMatcher(IPM_MemoryAlignment, InsnVarID),
1559*0fca6ea1SDimitry Andric         MMOIdx(MMOIdx), MinAlign(MinAlign) {
1560*0fca6ea1SDimitry Andric     assert(MinAlign > 0);
1561*0fca6ea1SDimitry Andric   }
1562*0fca6ea1SDimitry Andric 
1563*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1564*0fca6ea1SDimitry Andric     return P->getKind() == IPM_MemoryAlignment;
1565*0fca6ea1SDimitry Andric   }
1566*0fca6ea1SDimitry Andric 
1567*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override;
1568*0fca6ea1SDimitry Andric 
1569*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1570*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1571*0fca6ea1SDimitry Andric };
1572*0fca6ea1SDimitry Andric 
1573*0fca6ea1SDimitry Andric /// Generates code to check that the size of an MMO is less-than, equal-to, or
1574*0fca6ea1SDimitry Andric /// greater than a given LLT.
1575*0fca6ea1SDimitry Andric class MemoryVsLLTSizePredicateMatcher : public InstructionPredicateMatcher {
1576*0fca6ea1SDimitry Andric public:
1577*0fca6ea1SDimitry Andric   enum RelationKind {
1578*0fca6ea1SDimitry Andric     GreaterThan,
1579*0fca6ea1SDimitry Andric     EqualTo,
1580*0fca6ea1SDimitry Andric     LessThan,
1581*0fca6ea1SDimitry Andric   };
1582*0fca6ea1SDimitry Andric 
1583*0fca6ea1SDimitry Andric protected:
1584*0fca6ea1SDimitry Andric   unsigned MMOIdx;
1585*0fca6ea1SDimitry Andric   RelationKind Relation;
1586*0fca6ea1SDimitry Andric   unsigned OpIdx;
1587*0fca6ea1SDimitry Andric 
1588*0fca6ea1SDimitry Andric public:
1589*0fca6ea1SDimitry Andric   MemoryVsLLTSizePredicateMatcher(unsigned InsnVarID, unsigned MMOIdx,
1590*0fca6ea1SDimitry Andric                                   enum RelationKind Relation, unsigned OpIdx)
1591*0fca6ea1SDimitry Andric       : InstructionPredicateMatcher(IPM_MemoryVsLLTSize, InsnVarID),
1592*0fca6ea1SDimitry Andric         MMOIdx(MMOIdx), Relation(Relation), OpIdx(OpIdx) {}
1593*0fca6ea1SDimitry Andric 
1594*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1595*0fca6ea1SDimitry Andric     return P->getKind() == IPM_MemoryVsLLTSize;
1596*0fca6ea1SDimitry Andric   }
1597*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override;
1598*0fca6ea1SDimitry Andric 
1599*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1600*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1601*0fca6ea1SDimitry Andric };
1602*0fca6ea1SDimitry Andric 
1603*0fca6ea1SDimitry Andric // Matcher for immAllOnesV/immAllZerosV
1604*0fca6ea1SDimitry Andric class VectorSplatImmPredicateMatcher : public InstructionPredicateMatcher {
1605*0fca6ea1SDimitry Andric public:
1606*0fca6ea1SDimitry Andric   enum SplatKind { AllZeros, AllOnes };
1607*0fca6ea1SDimitry Andric 
1608*0fca6ea1SDimitry Andric private:
1609*0fca6ea1SDimitry Andric   SplatKind Kind;
1610*0fca6ea1SDimitry Andric 
1611*0fca6ea1SDimitry Andric public:
1612*0fca6ea1SDimitry Andric   VectorSplatImmPredicateMatcher(unsigned InsnVarID, SplatKind K)
1613*0fca6ea1SDimitry Andric       : InstructionPredicateMatcher(IPM_VectorSplatImm, InsnVarID), Kind(K) {}
1614*0fca6ea1SDimitry Andric 
1615*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1616*0fca6ea1SDimitry Andric     return P->getKind() == IPM_VectorSplatImm;
1617*0fca6ea1SDimitry Andric   }
1618*0fca6ea1SDimitry Andric 
1619*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
1620*0fca6ea1SDimitry Andric     return InstructionPredicateMatcher::isIdentical(B) &&
1621*0fca6ea1SDimitry Andric            Kind == static_cast<const VectorSplatImmPredicateMatcher &>(B).Kind;
1622*0fca6ea1SDimitry Andric   }
1623*0fca6ea1SDimitry Andric 
1624*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1625*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1626*0fca6ea1SDimitry Andric };
1627*0fca6ea1SDimitry Andric 
1628*0fca6ea1SDimitry Andric /// Generates code to check an arbitrary C++ instruction predicate.
1629*0fca6ea1SDimitry Andric class GenericInstructionPredicateMatcher : public InstructionPredicateMatcher {
1630*0fca6ea1SDimitry Andric protected:
1631*0fca6ea1SDimitry Andric   std::string EnumVal;
1632*0fca6ea1SDimitry Andric 
1633*0fca6ea1SDimitry Andric public:
1634*0fca6ea1SDimitry Andric   GenericInstructionPredicateMatcher(unsigned InsnVarID,
1635*0fca6ea1SDimitry Andric                                      TreePredicateFn Predicate);
1636*0fca6ea1SDimitry Andric 
1637*0fca6ea1SDimitry Andric   GenericInstructionPredicateMatcher(unsigned InsnVarID,
1638*0fca6ea1SDimitry Andric                                      const std::string &EnumVal)
1639*0fca6ea1SDimitry Andric       : InstructionPredicateMatcher(IPM_GenericPredicate, InsnVarID),
1640*0fca6ea1SDimitry Andric         EnumVal(EnumVal) {}
1641*0fca6ea1SDimitry Andric 
1642*0fca6ea1SDimitry Andric   static bool classof(const InstructionPredicateMatcher *P) {
1643*0fca6ea1SDimitry Andric     return P->getKind() == IPM_GenericPredicate;
1644*0fca6ea1SDimitry Andric   }
1645*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override;
1646*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1647*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1648*0fca6ea1SDimitry Andric };
1649*0fca6ea1SDimitry Andric 
1650*0fca6ea1SDimitry Andric class MIFlagsInstructionPredicateMatcher : public InstructionPredicateMatcher {
1651*0fca6ea1SDimitry Andric   SmallVector<StringRef, 2> Flags;
1652*0fca6ea1SDimitry Andric   bool CheckNot; // false = GIM_MIFlags, true = GIM_MIFlagsNot
1653*0fca6ea1SDimitry Andric 
1654*0fca6ea1SDimitry Andric public:
1655*0fca6ea1SDimitry Andric   MIFlagsInstructionPredicateMatcher(unsigned InsnVarID,
1656*0fca6ea1SDimitry Andric                                      ArrayRef<StringRef> FlagsToCheck,
1657*0fca6ea1SDimitry Andric                                      bool CheckNot = false)
1658*0fca6ea1SDimitry Andric       : InstructionPredicateMatcher(IPM_MIFlags, InsnVarID),
1659*0fca6ea1SDimitry Andric         Flags(FlagsToCheck), CheckNot(CheckNot) {
1660*0fca6ea1SDimitry Andric     sort(Flags);
1661*0fca6ea1SDimitry Andric   }
1662*0fca6ea1SDimitry Andric 
1663*0fca6ea1SDimitry Andric   static bool classof(const InstructionPredicateMatcher *P) {
1664*0fca6ea1SDimitry Andric     return P->getKind() == IPM_MIFlags;
1665*0fca6ea1SDimitry Andric   }
1666*0fca6ea1SDimitry Andric 
1667*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override;
1668*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1669*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override;
1670*0fca6ea1SDimitry Andric };
1671*0fca6ea1SDimitry Andric 
1672*0fca6ea1SDimitry Andric /// Generates code to check for the absence of use of the result.
1673*0fca6ea1SDimitry Andric // TODO? Generalize this to support checking for one use.
1674*0fca6ea1SDimitry Andric class NoUsePredicateMatcher : public InstructionPredicateMatcher {
1675*0fca6ea1SDimitry Andric public:
1676*0fca6ea1SDimitry Andric   NoUsePredicateMatcher(unsigned InsnVarID)
1677*0fca6ea1SDimitry Andric       : InstructionPredicateMatcher(IPM_NoUse, InsnVarID) {}
1678*0fca6ea1SDimitry Andric 
1679*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1680*0fca6ea1SDimitry Andric     return P->getKind() == IPM_NoUse;
1681*0fca6ea1SDimitry Andric   }
1682*0fca6ea1SDimitry Andric 
1683*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
1684*0fca6ea1SDimitry Andric     return InstructionPredicateMatcher::isIdentical(B);
1685*0fca6ea1SDimitry Andric   }
1686*0fca6ea1SDimitry Andric 
1687*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1688*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override {
1689*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_CheckHasNoUse")
1690*0fca6ea1SDimitry Andric           << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1691*0fca6ea1SDimitry Andric           << MatchTable::LineBreak;
1692*0fca6ea1SDimitry Andric   }
1693*0fca6ea1SDimitry Andric };
1694*0fca6ea1SDimitry Andric 
1695*0fca6ea1SDimitry Andric /// Generates code to check that the first result has only one use.
1696*0fca6ea1SDimitry Andric class OneUsePredicateMatcher : public InstructionPredicateMatcher {
1697*0fca6ea1SDimitry Andric public:
1698*0fca6ea1SDimitry Andric   OneUsePredicateMatcher(unsigned InsnVarID)
1699*0fca6ea1SDimitry Andric       : InstructionPredicateMatcher(IPM_OneUse, InsnVarID) {}
1700*0fca6ea1SDimitry Andric 
1701*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1702*0fca6ea1SDimitry Andric     return P->getKind() == IPM_OneUse;
1703*0fca6ea1SDimitry Andric   }
1704*0fca6ea1SDimitry Andric 
1705*0fca6ea1SDimitry Andric   bool isIdentical(const PredicateMatcher &B) const override {
1706*0fca6ea1SDimitry Andric     return InstructionPredicateMatcher::isIdentical(B);
1707*0fca6ea1SDimitry Andric   }
1708*0fca6ea1SDimitry Andric 
1709*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1710*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override {
1711*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_CheckHasOneUse")
1712*0fca6ea1SDimitry Andric           << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1713*0fca6ea1SDimitry Andric           << MatchTable::LineBreak;
1714*0fca6ea1SDimitry Andric   }
1715*0fca6ea1SDimitry Andric };
1716*0fca6ea1SDimitry Andric 
1717*0fca6ea1SDimitry Andric /// Generates code to check that a set of predicates and operands match for a
1718*0fca6ea1SDimitry Andric /// particular instruction.
1719*0fca6ea1SDimitry Andric ///
1720*0fca6ea1SDimitry Andric /// Typical predicates include:
1721*0fca6ea1SDimitry Andric /// * Has a specific opcode.
1722*0fca6ea1SDimitry Andric /// * Has an nsw/nuw flag or doesn't.
1723*0fca6ea1SDimitry Andric class InstructionMatcher final : public PredicateListMatcher<PredicateMatcher> {
1724*0fca6ea1SDimitry Andric protected:
1725*0fca6ea1SDimitry Andric   typedef std::vector<std::unique_ptr<OperandMatcher>> OperandVec;
1726*0fca6ea1SDimitry Andric 
1727*0fca6ea1SDimitry Andric   RuleMatcher &Rule;
1728*0fca6ea1SDimitry Andric 
1729*0fca6ea1SDimitry Andric   /// The operands to match. All rendered operands must be present even if the
1730*0fca6ea1SDimitry Andric   /// condition is always true.
1731*0fca6ea1SDimitry Andric   OperandVec Operands;
1732*0fca6ea1SDimitry Andric   bool NumOperandsCheck = true;
1733*0fca6ea1SDimitry Andric 
1734*0fca6ea1SDimitry Andric   std::string SymbolicName;
1735*0fca6ea1SDimitry Andric   unsigned InsnVarID;
1736*0fca6ea1SDimitry Andric 
1737*0fca6ea1SDimitry Andric   /// PhysRegInputs - List list has an entry for each explicitly specified
1738*0fca6ea1SDimitry Andric   /// physreg input to the pattern.  The first elt is the Register node, the
1739*0fca6ea1SDimitry Andric   /// second is the recorded slot number the input pattern match saved it in.
1740*0fca6ea1SDimitry Andric   SmallVector<std::pair<Record *, unsigned>, 2> PhysRegInputs;
1741*0fca6ea1SDimitry Andric 
1742*0fca6ea1SDimitry Andric public:
1743*0fca6ea1SDimitry Andric   InstructionMatcher(RuleMatcher &Rule, StringRef SymbolicName,
1744*0fca6ea1SDimitry Andric                      bool NumOpsCheck = true)
1745*0fca6ea1SDimitry Andric       : Rule(Rule), NumOperandsCheck(NumOpsCheck), SymbolicName(SymbolicName) {
1746*0fca6ea1SDimitry Andric     // We create a new instruction matcher.
1747*0fca6ea1SDimitry Andric     // Get a new ID for that instruction.
1748*0fca6ea1SDimitry Andric     InsnVarID = Rule.implicitlyDefineInsnVar(*this);
1749*0fca6ea1SDimitry Andric   }
1750*0fca6ea1SDimitry Andric 
1751*0fca6ea1SDimitry Andric   /// Construct a new instruction predicate and add it to the matcher.
1752*0fca6ea1SDimitry Andric   template <class Kind, class... Args>
1753*0fca6ea1SDimitry Andric   std::optional<Kind *> addPredicate(Args &&...args) {
1754*0fca6ea1SDimitry Andric     Predicates.emplace_back(
1755*0fca6ea1SDimitry Andric         std::make_unique<Kind>(getInsnVarID(), std::forward<Args>(args)...));
1756*0fca6ea1SDimitry Andric     return static_cast<Kind *>(Predicates.back().get());
1757*0fca6ea1SDimitry Andric   }
1758*0fca6ea1SDimitry Andric 
1759*0fca6ea1SDimitry Andric   RuleMatcher &getRuleMatcher() const { return Rule; }
1760*0fca6ea1SDimitry Andric 
1761*0fca6ea1SDimitry Andric   unsigned getInsnVarID() const { return InsnVarID; }
1762*0fca6ea1SDimitry Andric 
1763*0fca6ea1SDimitry Andric   /// Add an operand to the matcher.
1764*0fca6ea1SDimitry Andric   OperandMatcher &addOperand(unsigned OpIdx, const std::string &SymbolicName,
1765*0fca6ea1SDimitry Andric                              unsigned AllocatedTemporariesBaseID);
1766*0fca6ea1SDimitry Andric   OperandMatcher &getOperand(unsigned OpIdx);
1767*0fca6ea1SDimitry Andric   OperandMatcher &addPhysRegInput(Record *Reg, unsigned OpIdx,
1768*0fca6ea1SDimitry Andric                                   unsigned TempOpIdx);
1769*0fca6ea1SDimitry Andric 
1770*0fca6ea1SDimitry Andric   ArrayRef<std::pair<Record *, unsigned>> getPhysRegInputs() const {
1771*0fca6ea1SDimitry Andric     return PhysRegInputs;
1772*0fca6ea1SDimitry Andric   }
1773*0fca6ea1SDimitry Andric 
1774*0fca6ea1SDimitry Andric   StringRef getSymbolicName() const { return SymbolicName; }
1775*0fca6ea1SDimitry Andric   unsigned getNumOperands() const { return Operands.size(); }
1776*0fca6ea1SDimitry Andric   OperandVec::iterator operands_begin() { return Operands.begin(); }
1777*0fca6ea1SDimitry Andric   OperandVec::iterator operands_end() { return Operands.end(); }
1778*0fca6ea1SDimitry Andric   iterator_range<OperandVec::iterator> operands() {
1779*0fca6ea1SDimitry Andric     return make_range(operands_begin(), operands_end());
1780*0fca6ea1SDimitry Andric   }
1781*0fca6ea1SDimitry Andric   OperandVec::const_iterator operands_begin() const { return Operands.begin(); }
1782*0fca6ea1SDimitry Andric   OperandVec::const_iterator operands_end() const { return Operands.end(); }
1783*0fca6ea1SDimitry Andric   iterator_range<OperandVec::const_iterator> operands() const {
1784*0fca6ea1SDimitry Andric     return make_range(operands_begin(), operands_end());
1785*0fca6ea1SDimitry Andric   }
1786*0fca6ea1SDimitry Andric   bool operands_empty() const { return Operands.empty(); }
1787*0fca6ea1SDimitry Andric 
1788*0fca6ea1SDimitry Andric   void pop_front() { Operands.erase(Operands.begin()); }
1789*0fca6ea1SDimitry Andric 
1790*0fca6ea1SDimitry Andric   void optimize();
1791*0fca6ea1SDimitry Andric 
1792*0fca6ea1SDimitry Andric   /// Emit MatchTable opcodes that test whether the instruction named in
1793*0fca6ea1SDimitry Andric   /// InsnVarName matches all the predicates and all the operands.
1794*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule);
1795*0fca6ea1SDimitry Andric 
1796*0fca6ea1SDimitry Andric   /// Compare the priority of this object and B.
1797*0fca6ea1SDimitry Andric   ///
1798*0fca6ea1SDimitry Andric   /// Returns true if this object is more important than B.
1799*0fca6ea1SDimitry Andric   bool isHigherPriorityThan(InstructionMatcher &B);
1800*0fca6ea1SDimitry Andric 
1801*0fca6ea1SDimitry Andric   /// Report the maximum number of temporary operands needed by the instruction
1802*0fca6ea1SDimitry Andric   /// matcher.
1803*0fca6ea1SDimitry Andric   unsigned countRendererFns();
1804*0fca6ea1SDimitry Andric 
1805*0fca6ea1SDimitry Andric   InstructionOpcodeMatcher &getOpcodeMatcher() {
1806*0fca6ea1SDimitry Andric     for (auto &P : predicates())
1807*0fca6ea1SDimitry Andric       if (auto *OpMatcher = dyn_cast<InstructionOpcodeMatcher>(P.get()))
1808*0fca6ea1SDimitry Andric         return *OpMatcher;
1809*0fca6ea1SDimitry Andric     llvm_unreachable("Didn't find an opcode matcher");
1810*0fca6ea1SDimitry Andric   }
1811*0fca6ea1SDimitry Andric 
1812*0fca6ea1SDimitry Andric   bool isConstantInstruction() {
1813*0fca6ea1SDimitry Andric     return getOpcodeMatcher().isConstantInstruction();
1814*0fca6ea1SDimitry Andric   }
1815*0fca6ea1SDimitry Andric 
1816*0fca6ea1SDimitry Andric   StringRef getOpcode() { return getOpcodeMatcher().getOpcode(); }
1817*0fca6ea1SDimitry Andric };
1818*0fca6ea1SDimitry Andric 
1819*0fca6ea1SDimitry Andric /// Generates code to check that the operand is a register defined by an
1820*0fca6ea1SDimitry Andric /// instruction that matches the given instruction matcher.
1821*0fca6ea1SDimitry Andric ///
1822*0fca6ea1SDimitry Andric /// For example, the pattern:
1823*0fca6ea1SDimitry Andric ///   (set $dst, (G_MUL (G_ADD $src1, $src2), $src3))
1824*0fca6ea1SDimitry Andric /// would use an InstructionOperandMatcher for operand 1 of the G_MUL to match
1825*0fca6ea1SDimitry Andric /// the:
1826*0fca6ea1SDimitry Andric ///   (G_ADD $src1, $src2)
1827*0fca6ea1SDimitry Andric /// subpattern.
1828*0fca6ea1SDimitry Andric class InstructionOperandMatcher : public OperandPredicateMatcher {
1829*0fca6ea1SDimitry Andric protected:
1830*0fca6ea1SDimitry Andric   std::unique_ptr<InstructionMatcher> InsnMatcher;
1831*0fca6ea1SDimitry Andric 
1832*0fca6ea1SDimitry Andric   GISelFlags Flags;
1833*0fca6ea1SDimitry Andric 
1834*0fca6ea1SDimitry Andric public:
1835*0fca6ea1SDimitry Andric   InstructionOperandMatcher(unsigned InsnVarID, unsigned OpIdx,
1836*0fca6ea1SDimitry Andric                             RuleMatcher &Rule, StringRef SymbolicName,
1837*0fca6ea1SDimitry Andric                             bool NumOpsCheck = true)
1838*0fca6ea1SDimitry Andric       : OperandPredicateMatcher(OPM_Instruction, InsnVarID, OpIdx),
1839*0fca6ea1SDimitry Andric         InsnMatcher(new InstructionMatcher(Rule, SymbolicName, NumOpsCheck)),
1840*0fca6ea1SDimitry Andric         Flags(Rule.getGISelFlags()) {}
1841*0fca6ea1SDimitry Andric 
1842*0fca6ea1SDimitry Andric   static bool classof(const PredicateMatcher *P) {
1843*0fca6ea1SDimitry Andric     return P->getKind() == OPM_Instruction;
1844*0fca6ea1SDimitry Andric   }
1845*0fca6ea1SDimitry Andric 
1846*0fca6ea1SDimitry Andric   InstructionMatcher &getInsnMatcher() const { return *InsnMatcher; }
1847*0fca6ea1SDimitry Andric 
1848*0fca6ea1SDimitry Andric   void emitCaptureOpcodes(MatchTable &Table, RuleMatcher &Rule) const;
1849*0fca6ea1SDimitry Andric   void emitPredicateOpcodes(MatchTable &Table,
1850*0fca6ea1SDimitry Andric                             RuleMatcher &Rule) const override {
1851*0fca6ea1SDimitry Andric     emitCaptureOpcodes(Table, Rule);
1852*0fca6ea1SDimitry Andric     InsnMatcher->emitPredicateOpcodes(Table, Rule);
1853*0fca6ea1SDimitry Andric   }
1854*0fca6ea1SDimitry Andric 
1855*0fca6ea1SDimitry Andric   bool isHigherPriorityThan(const OperandPredicateMatcher &B) const override;
1856*0fca6ea1SDimitry Andric 
1857*0fca6ea1SDimitry Andric   /// Report the maximum number of temporary operands needed by the predicate
1858*0fca6ea1SDimitry Andric   /// matcher.
1859*0fca6ea1SDimitry Andric   unsigned countRendererFns() const override {
1860*0fca6ea1SDimitry Andric     return InsnMatcher->countRendererFns();
1861*0fca6ea1SDimitry Andric   }
1862*0fca6ea1SDimitry Andric };
1863*0fca6ea1SDimitry Andric 
1864*0fca6ea1SDimitry Andric //===- Actions ------------------------------------------------------------===//
1865*0fca6ea1SDimitry Andric class OperandRenderer {
1866*0fca6ea1SDimitry Andric public:
1867*0fca6ea1SDimitry Andric   enum RendererKind {
1868*0fca6ea1SDimitry Andric     OR_Copy,
1869*0fca6ea1SDimitry Andric     OR_CopyOrAddZeroReg,
1870*0fca6ea1SDimitry Andric     OR_CopySubReg,
1871*0fca6ea1SDimitry Andric     OR_CopyPhysReg,
1872*0fca6ea1SDimitry Andric     OR_CopyConstantAsImm,
1873*0fca6ea1SDimitry Andric     OR_CopyFConstantAsFPImm,
1874*0fca6ea1SDimitry Andric     OR_Imm,
1875*0fca6ea1SDimitry Andric     OR_SubRegIndex,
1876*0fca6ea1SDimitry Andric     OR_Register,
1877*0fca6ea1SDimitry Andric     OR_TempRegister,
1878*0fca6ea1SDimitry Andric     OR_ComplexPattern,
1879*0fca6ea1SDimitry Andric     OR_Intrinsic,
1880*0fca6ea1SDimitry Andric     OR_Custom,
1881*0fca6ea1SDimitry Andric     OR_CustomOperand
1882*0fca6ea1SDimitry Andric   };
1883*0fca6ea1SDimitry Andric 
1884*0fca6ea1SDimitry Andric protected:
1885*0fca6ea1SDimitry Andric   RendererKind Kind;
1886*0fca6ea1SDimitry Andric 
1887*0fca6ea1SDimitry Andric public:
1888*0fca6ea1SDimitry Andric   OperandRenderer(RendererKind Kind) : Kind(Kind) {}
1889*0fca6ea1SDimitry Andric   virtual ~OperandRenderer();
1890*0fca6ea1SDimitry Andric 
1891*0fca6ea1SDimitry Andric   RendererKind getKind() const { return Kind; }
1892*0fca6ea1SDimitry Andric 
1893*0fca6ea1SDimitry Andric   virtual void emitRenderOpcodes(MatchTable &Table,
1894*0fca6ea1SDimitry Andric                                  RuleMatcher &Rule) const = 0;
1895*0fca6ea1SDimitry Andric };
1896*0fca6ea1SDimitry Andric 
1897*0fca6ea1SDimitry Andric /// A CopyRenderer emits code to copy a single operand from an existing
1898*0fca6ea1SDimitry Andric /// instruction to the one being built.
1899*0fca6ea1SDimitry Andric class CopyRenderer : public OperandRenderer {
1900*0fca6ea1SDimitry Andric protected:
1901*0fca6ea1SDimitry Andric   unsigned NewInsnID;
1902*0fca6ea1SDimitry Andric   /// The name of the operand.
1903*0fca6ea1SDimitry Andric   const StringRef SymbolicName;
1904*0fca6ea1SDimitry Andric 
1905*0fca6ea1SDimitry Andric public:
1906*0fca6ea1SDimitry Andric   CopyRenderer(unsigned NewInsnID, StringRef SymbolicName)
1907*0fca6ea1SDimitry Andric       : OperandRenderer(OR_Copy), NewInsnID(NewInsnID),
1908*0fca6ea1SDimitry Andric         SymbolicName(SymbolicName) {
1909*0fca6ea1SDimitry Andric     assert(!SymbolicName.empty() && "Cannot copy from an unspecified source");
1910*0fca6ea1SDimitry Andric   }
1911*0fca6ea1SDimitry Andric 
1912*0fca6ea1SDimitry Andric   static bool classof(const OperandRenderer *R) {
1913*0fca6ea1SDimitry Andric     return R->getKind() == OR_Copy;
1914*0fca6ea1SDimitry Andric   }
1915*0fca6ea1SDimitry Andric 
1916*0fca6ea1SDimitry Andric   StringRef getSymbolicName() const { return SymbolicName; }
1917*0fca6ea1SDimitry Andric 
1918*0fca6ea1SDimitry Andric   static void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule,
1919*0fca6ea1SDimitry Andric                                 unsigned NewInsnID, unsigned OldInsnID,
1920*0fca6ea1SDimitry Andric                                 unsigned OpIdx, StringRef Name);
1921*0fca6ea1SDimitry Andric 
1922*0fca6ea1SDimitry Andric   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
1923*0fca6ea1SDimitry Andric };
1924*0fca6ea1SDimitry Andric 
1925*0fca6ea1SDimitry Andric /// A CopyRenderer emits code to copy a virtual register to a specific physical
1926*0fca6ea1SDimitry Andric /// register.
1927*0fca6ea1SDimitry Andric class CopyPhysRegRenderer : public OperandRenderer {
1928*0fca6ea1SDimitry Andric protected:
1929*0fca6ea1SDimitry Andric   unsigned NewInsnID;
1930*0fca6ea1SDimitry Andric   Record *PhysReg;
1931*0fca6ea1SDimitry Andric 
1932*0fca6ea1SDimitry Andric public:
1933*0fca6ea1SDimitry Andric   CopyPhysRegRenderer(unsigned NewInsnID, Record *Reg)
1934*0fca6ea1SDimitry Andric       : OperandRenderer(OR_CopyPhysReg), NewInsnID(NewInsnID), PhysReg(Reg) {
1935*0fca6ea1SDimitry Andric     assert(PhysReg);
1936*0fca6ea1SDimitry Andric   }
1937*0fca6ea1SDimitry Andric 
1938*0fca6ea1SDimitry Andric   static bool classof(const OperandRenderer *R) {
1939*0fca6ea1SDimitry Andric     return R->getKind() == OR_CopyPhysReg;
1940*0fca6ea1SDimitry Andric   }
1941*0fca6ea1SDimitry Andric 
1942*0fca6ea1SDimitry Andric   Record *getPhysReg() const { return PhysReg; }
1943*0fca6ea1SDimitry Andric 
1944*0fca6ea1SDimitry Andric   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
1945*0fca6ea1SDimitry Andric };
1946*0fca6ea1SDimitry Andric 
1947*0fca6ea1SDimitry Andric /// A CopyOrAddZeroRegRenderer emits code to copy a single operand from an
1948*0fca6ea1SDimitry Andric /// existing instruction to the one being built. If the operand turns out to be
1949*0fca6ea1SDimitry Andric /// a 'G_CONSTANT 0' then it replaces the operand with a zero register.
1950*0fca6ea1SDimitry Andric class CopyOrAddZeroRegRenderer : public OperandRenderer {
1951*0fca6ea1SDimitry Andric protected:
1952*0fca6ea1SDimitry Andric   unsigned NewInsnID;
1953*0fca6ea1SDimitry Andric   /// The name of the operand.
1954*0fca6ea1SDimitry Andric   const StringRef SymbolicName;
1955*0fca6ea1SDimitry Andric   const Record *ZeroRegisterDef;
1956*0fca6ea1SDimitry Andric 
1957*0fca6ea1SDimitry Andric public:
1958*0fca6ea1SDimitry Andric   CopyOrAddZeroRegRenderer(unsigned NewInsnID, StringRef SymbolicName,
1959*0fca6ea1SDimitry Andric                            Record *ZeroRegisterDef)
1960*0fca6ea1SDimitry Andric       : OperandRenderer(OR_CopyOrAddZeroReg), NewInsnID(NewInsnID),
1961*0fca6ea1SDimitry Andric         SymbolicName(SymbolicName), ZeroRegisterDef(ZeroRegisterDef) {
1962*0fca6ea1SDimitry Andric     assert(!SymbolicName.empty() && "Cannot copy from an unspecified source");
1963*0fca6ea1SDimitry Andric   }
1964*0fca6ea1SDimitry Andric 
1965*0fca6ea1SDimitry Andric   static bool classof(const OperandRenderer *R) {
1966*0fca6ea1SDimitry Andric     return R->getKind() == OR_CopyOrAddZeroReg;
1967*0fca6ea1SDimitry Andric   }
1968*0fca6ea1SDimitry Andric 
1969*0fca6ea1SDimitry Andric   StringRef getSymbolicName() const { return SymbolicName; }
1970*0fca6ea1SDimitry Andric 
1971*0fca6ea1SDimitry Andric   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
1972*0fca6ea1SDimitry Andric };
1973*0fca6ea1SDimitry Andric 
1974*0fca6ea1SDimitry Andric /// A CopyConstantAsImmRenderer emits code to render a G_CONSTANT instruction to
1975*0fca6ea1SDimitry Andric /// an extended immediate operand.
1976*0fca6ea1SDimitry Andric class CopyConstantAsImmRenderer : public OperandRenderer {
1977*0fca6ea1SDimitry Andric protected:
1978*0fca6ea1SDimitry Andric   unsigned NewInsnID;
1979*0fca6ea1SDimitry Andric   /// The name of the operand.
1980*0fca6ea1SDimitry Andric   const std::string SymbolicName;
1981*0fca6ea1SDimitry Andric   bool Signed;
1982*0fca6ea1SDimitry Andric 
1983*0fca6ea1SDimitry Andric public:
1984*0fca6ea1SDimitry Andric   CopyConstantAsImmRenderer(unsigned NewInsnID, StringRef SymbolicName)
1985*0fca6ea1SDimitry Andric       : OperandRenderer(OR_CopyConstantAsImm), NewInsnID(NewInsnID),
1986*0fca6ea1SDimitry Andric         SymbolicName(SymbolicName), Signed(true) {}
1987*0fca6ea1SDimitry Andric 
1988*0fca6ea1SDimitry Andric   static bool classof(const OperandRenderer *R) {
1989*0fca6ea1SDimitry Andric     return R->getKind() == OR_CopyConstantAsImm;
1990*0fca6ea1SDimitry Andric   }
1991*0fca6ea1SDimitry Andric 
1992*0fca6ea1SDimitry Andric   StringRef getSymbolicName() const { return SymbolicName; }
1993*0fca6ea1SDimitry Andric 
1994*0fca6ea1SDimitry Andric   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
1995*0fca6ea1SDimitry Andric };
1996*0fca6ea1SDimitry Andric 
1997*0fca6ea1SDimitry Andric /// A CopyFConstantAsFPImmRenderer emits code to render a G_FCONSTANT
1998*0fca6ea1SDimitry Andric /// instruction to an extended immediate operand.
1999*0fca6ea1SDimitry Andric class CopyFConstantAsFPImmRenderer : public OperandRenderer {
2000*0fca6ea1SDimitry Andric protected:
2001*0fca6ea1SDimitry Andric   unsigned NewInsnID;
2002*0fca6ea1SDimitry Andric   /// The name of the operand.
2003*0fca6ea1SDimitry Andric   const std::string SymbolicName;
2004*0fca6ea1SDimitry Andric 
2005*0fca6ea1SDimitry Andric public:
2006*0fca6ea1SDimitry Andric   CopyFConstantAsFPImmRenderer(unsigned NewInsnID, StringRef SymbolicName)
2007*0fca6ea1SDimitry Andric       : OperandRenderer(OR_CopyFConstantAsFPImm), NewInsnID(NewInsnID),
2008*0fca6ea1SDimitry Andric         SymbolicName(SymbolicName) {}
2009*0fca6ea1SDimitry Andric 
2010*0fca6ea1SDimitry Andric   static bool classof(const OperandRenderer *R) {
2011*0fca6ea1SDimitry Andric     return R->getKind() == OR_CopyFConstantAsFPImm;
2012*0fca6ea1SDimitry Andric   }
2013*0fca6ea1SDimitry Andric 
2014*0fca6ea1SDimitry Andric   StringRef getSymbolicName() const { return SymbolicName; }
2015*0fca6ea1SDimitry Andric 
2016*0fca6ea1SDimitry Andric   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2017*0fca6ea1SDimitry Andric };
2018*0fca6ea1SDimitry Andric 
2019*0fca6ea1SDimitry Andric /// A CopySubRegRenderer emits code to copy a single register operand from an
2020*0fca6ea1SDimitry Andric /// existing instruction to the one being built and indicate that only a
2021*0fca6ea1SDimitry Andric /// subregister should be copied.
2022*0fca6ea1SDimitry Andric class CopySubRegRenderer : public OperandRenderer {
2023*0fca6ea1SDimitry Andric protected:
2024*0fca6ea1SDimitry Andric   unsigned NewInsnID;
2025*0fca6ea1SDimitry Andric   /// The name of the operand.
2026*0fca6ea1SDimitry Andric   const StringRef SymbolicName;
2027*0fca6ea1SDimitry Andric   /// The subregister to extract.
2028*0fca6ea1SDimitry Andric   const CodeGenSubRegIndex *SubReg;
2029*0fca6ea1SDimitry Andric 
2030*0fca6ea1SDimitry Andric public:
2031*0fca6ea1SDimitry Andric   CopySubRegRenderer(unsigned NewInsnID, StringRef SymbolicName,
2032*0fca6ea1SDimitry Andric                      const CodeGenSubRegIndex *SubReg)
2033*0fca6ea1SDimitry Andric       : OperandRenderer(OR_CopySubReg), NewInsnID(NewInsnID),
2034*0fca6ea1SDimitry Andric         SymbolicName(SymbolicName), SubReg(SubReg) {}
2035*0fca6ea1SDimitry Andric 
2036*0fca6ea1SDimitry Andric   static bool classof(const OperandRenderer *R) {
2037*0fca6ea1SDimitry Andric     return R->getKind() == OR_CopySubReg;
2038*0fca6ea1SDimitry Andric   }
2039*0fca6ea1SDimitry Andric 
2040*0fca6ea1SDimitry Andric   StringRef getSymbolicName() const { return SymbolicName; }
2041*0fca6ea1SDimitry Andric 
2042*0fca6ea1SDimitry Andric   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2043*0fca6ea1SDimitry Andric };
2044*0fca6ea1SDimitry Andric 
2045*0fca6ea1SDimitry Andric /// Adds a specific physical register to the instruction being built.
2046*0fca6ea1SDimitry Andric /// This is typically useful for WZR/XZR on AArch64.
2047*0fca6ea1SDimitry Andric class AddRegisterRenderer : public OperandRenderer {
2048*0fca6ea1SDimitry Andric protected:
2049*0fca6ea1SDimitry Andric   unsigned InsnID;
2050*0fca6ea1SDimitry Andric   const Record *RegisterDef;
2051*0fca6ea1SDimitry Andric   bool IsDef;
2052*0fca6ea1SDimitry Andric   const CodeGenTarget &Target;
2053*0fca6ea1SDimitry Andric 
2054*0fca6ea1SDimitry Andric public:
2055*0fca6ea1SDimitry Andric   AddRegisterRenderer(unsigned InsnID, const CodeGenTarget &Target,
2056*0fca6ea1SDimitry Andric                       const Record *RegisterDef, bool IsDef = false)
2057*0fca6ea1SDimitry Andric       : OperandRenderer(OR_Register), InsnID(InsnID), RegisterDef(RegisterDef),
2058*0fca6ea1SDimitry Andric         IsDef(IsDef), Target(Target) {}
2059*0fca6ea1SDimitry Andric 
2060*0fca6ea1SDimitry Andric   static bool classof(const OperandRenderer *R) {
2061*0fca6ea1SDimitry Andric     return R->getKind() == OR_Register;
2062*0fca6ea1SDimitry Andric   }
2063*0fca6ea1SDimitry Andric 
2064*0fca6ea1SDimitry Andric   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2065*0fca6ea1SDimitry Andric };
2066*0fca6ea1SDimitry Andric 
2067*0fca6ea1SDimitry Andric /// Adds a specific temporary virtual register to the instruction being built.
2068*0fca6ea1SDimitry Andric /// This is used to chain instructions together when emitting multiple
2069*0fca6ea1SDimitry Andric /// instructions.
2070*0fca6ea1SDimitry Andric class TempRegRenderer : public OperandRenderer {
2071*0fca6ea1SDimitry Andric protected:
2072*0fca6ea1SDimitry Andric   unsigned InsnID;
2073*0fca6ea1SDimitry Andric   unsigned TempRegID;
2074*0fca6ea1SDimitry Andric   const CodeGenSubRegIndex *SubRegIdx;
2075*0fca6ea1SDimitry Andric   bool IsDef;
2076*0fca6ea1SDimitry Andric   bool IsDead;
2077*0fca6ea1SDimitry Andric 
2078*0fca6ea1SDimitry Andric public:
2079*0fca6ea1SDimitry Andric   TempRegRenderer(unsigned InsnID, unsigned TempRegID, bool IsDef = false,
2080*0fca6ea1SDimitry Andric                   const CodeGenSubRegIndex *SubReg = nullptr,
2081*0fca6ea1SDimitry Andric                   bool IsDead = false)
2082*0fca6ea1SDimitry Andric       : OperandRenderer(OR_Register), InsnID(InsnID), TempRegID(TempRegID),
2083*0fca6ea1SDimitry Andric         SubRegIdx(SubReg), IsDef(IsDef), IsDead(IsDead) {}
2084*0fca6ea1SDimitry Andric 
2085*0fca6ea1SDimitry Andric   static bool classof(const OperandRenderer *R) {
2086*0fca6ea1SDimitry Andric     return R->getKind() == OR_TempRegister;
2087*0fca6ea1SDimitry Andric   }
2088*0fca6ea1SDimitry Andric 
2089*0fca6ea1SDimitry Andric   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2090*0fca6ea1SDimitry Andric };
2091*0fca6ea1SDimitry Andric 
2092*0fca6ea1SDimitry Andric /// Adds a specific immediate to the instruction being built.
2093*0fca6ea1SDimitry Andric /// If a LLT is passed, a ConstantInt immediate is created instead.
2094*0fca6ea1SDimitry Andric class ImmRenderer : public OperandRenderer {
2095*0fca6ea1SDimitry Andric protected:
2096*0fca6ea1SDimitry Andric   unsigned InsnID;
2097*0fca6ea1SDimitry Andric   int64_t Imm;
2098*0fca6ea1SDimitry Andric   std::optional<LLTCodeGenOrTempType> CImmLLT;
2099*0fca6ea1SDimitry Andric 
2100*0fca6ea1SDimitry Andric public:
2101*0fca6ea1SDimitry Andric   ImmRenderer(unsigned InsnID, int64_t Imm)
2102*0fca6ea1SDimitry Andric       : OperandRenderer(OR_Imm), InsnID(InsnID), Imm(Imm) {}
2103*0fca6ea1SDimitry Andric 
2104*0fca6ea1SDimitry Andric   ImmRenderer(unsigned InsnID, int64_t Imm, const LLTCodeGenOrTempType &CImmLLT)
2105*0fca6ea1SDimitry Andric       : OperandRenderer(OR_Imm), InsnID(InsnID), Imm(Imm), CImmLLT(CImmLLT) {
2106*0fca6ea1SDimitry Andric     if (CImmLLT.isLLTCodeGen())
2107*0fca6ea1SDimitry Andric       KnownTypes.insert(CImmLLT.getLLTCodeGen());
2108*0fca6ea1SDimitry Andric   }
2109*0fca6ea1SDimitry Andric 
2110*0fca6ea1SDimitry Andric   static bool classof(const OperandRenderer *R) {
2111*0fca6ea1SDimitry Andric     return R->getKind() == OR_Imm;
2112*0fca6ea1SDimitry Andric   }
2113*0fca6ea1SDimitry Andric 
2114*0fca6ea1SDimitry Andric   static void emitAddImm(MatchTable &Table, RuleMatcher &RM, unsigned InsnID,
2115*0fca6ea1SDimitry Andric                          int64_t Imm, StringRef ImmName = "Imm");
2116*0fca6ea1SDimitry Andric 
2117*0fca6ea1SDimitry Andric   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2118*0fca6ea1SDimitry Andric };
2119*0fca6ea1SDimitry Andric 
2120*0fca6ea1SDimitry Andric /// Adds an enum value for a subreg index to the instruction being built.
2121*0fca6ea1SDimitry Andric class SubRegIndexRenderer : public OperandRenderer {
2122*0fca6ea1SDimitry Andric protected:
2123*0fca6ea1SDimitry Andric   unsigned InsnID;
2124*0fca6ea1SDimitry Andric   const CodeGenSubRegIndex *SubRegIdx;
2125*0fca6ea1SDimitry Andric 
2126*0fca6ea1SDimitry Andric public:
2127*0fca6ea1SDimitry Andric   SubRegIndexRenderer(unsigned InsnID, const CodeGenSubRegIndex *SRI)
2128*0fca6ea1SDimitry Andric       : OperandRenderer(OR_SubRegIndex), InsnID(InsnID), SubRegIdx(SRI) {}
2129*0fca6ea1SDimitry Andric 
2130*0fca6ea1SDimitry Andric   static bool classof(const OperandRenderer *R) {
2131*0fca6ea1SDimitry Andric     return R->getKind() == OR_SubRegIndex;
2132*0fca6ea1SDimitry Andric   }
2133*0fca6ea1SDimitry Andric 
2134*0fca6ea1SDimitry Andric   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2135*0fca6ea1SDimitry Andric };
2136*0fca6ea1SDimitry Andric 
2137*0fca6ea1SDimitry Andric /// Adds operands by calling a renderer function supplied by the ComplexPattern
2138*0fca6ea1SDimitry Andric /// matcher function.
2139*0fca6ea1SDimitry Andric class RenderComplexPatternOperand : public OperandRenderer {
2140*0fca6ea1SDimitry Andric private:
2141*0fca6ea1SDimitry Andric   unsigned InsnID;
2142*0fca6ea1SDimitry Andric   const Record &TheDef;
2143*0fca6ea1SDimitry Andric   /// The name of the operand.
2144*0fca6ea1SDimitry Andric   const StringRef SymbolicName;
2145*0fca6ea1SDimitry Andric   /// The renderer number. This must be unique within a rule since it's used to
2146*0fca6ea1SDimitry Andric   /// identify a temporary variable to hold the renderer function.
2147*0fca6ea1SDimitry Andric   unsigned RendererID;
2148*0fca6ea1SDimitry Andric   /// When provided, this is the suboperand of the ComplexPattern operand to
2149*0fca6ea1SDimitry Andric   /// render. Otherwise all the suboperands will be rendered.
2150*0fca6ea1SDimitry Andric   std::optional<unsigned> SubOperand;
2151*0fca6ea1SDimitry Andric   /// The subregister to extract. Render the whole register if not specified.
2152*0fca6ea1SDimitry Andric   const CodeGenSubRegIndex *SubReg;
2153*0fca6ea1SDimitry Andric 
2154*0fca6ea1SDimitry Andric   unsigned getNumOperands() const {
2155*0fca6ea1SDimitry Andric     return TheDef.getValueAsDag("Operands")->getNumArgs();
2156*0fca6ea1SDimitry Andric   }
2157*0fca6ea1SDimitry Andric 
2158*0fca6ea1SDimitry Andric public:
2159*0fca6ea1SDimitry Andric   RenderComplexPatternOperand(unsigned InsnID, const Record &TheDef,
2160*0fca6ea1SDimitry Andric                               StringRef SymbolicName, unsigned RendererID,
2161*0fca6ea1SDimitry Andric                               std::optional<unsigned> SubOperand = std::nullopt,
2162*0fca6ea1SDimitry Andric                               const CodeGenSubRegIndex *SubReg = nullptr)
2163*0fca6ea1SDimitry Andric       : OperandRenderer(OR_ComplexPattern), InsnID(InsnID), TheDef(TheDef),
2164*0fca6ea1SDimitry Andric         SymbolicName(SymbolicName), RendererID(RendererID),
2165*0fca6ea1SDimitry Andric         SubOperand(SubOperand), SubReg(SubReg) {}
2166*0fca6ea1SDimitry Andric 
2167*0fca6ea1SDimitry Andric   static bool classof(const OperandRenderer *R) {
2168*0fca6ea1SDimitry Andric     return R->getKind() == OR_ComplexPattern;
2169*0fca6ea1SDimitry Andric   }
2170*0fca6ea1SDimitry Andric 
2171*0fca6ea1SDimitry Andric   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2172*0fca6ea1SDimitry Andric };
2173*0fca6ea1SDimitry Andric 
2174*0fca6ea1SDimitry Andric /// Adds an intrinsic ID operand to the instruction being built.
2175*0fca6ea1SDimitry Andric class IntrinsicIDRenderer : public OperandRenderer {
2176*0fca6ea1SDimitry Andric protected:
2177*0fca6ea1SDimitry Andric   unsigned InsnID;
2178*0fca6ea1SDimitry Andric   const CodeGenIntrinsic *II;
2179*0fca6ea1SDimitry Andric 
2180*0fca6ea1SDimitry Andric public:
2181*0fca6ea1SDimitry Andric   IntrinsicIDRenderer(unsigned InsnID, const CodeGenIntrinsic *II)
2182*0fca6ea1SDimitry Andric       : OperandRenderer(OR_Intrinsic), InsnID(InsnID), II(II) {}
2183*0fca6ea1SDimitry Andric 
2184*0fca6ea1SDimitry Andric   static bool classof(const OperandRenderer *R) {
2185*0fca6ea1SDimitry Andric     return R->getKind() == OR_Intrinsic;
2186*0fca6ea1SDimitry Andric   }
2187*0fca6ea1SDimitry Andric 
2188*0fca6ea1SDimitry Andric   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2189*0fca6ea1SDimitry Andric };
2190*0fca6ea1SDimitry Andric 
2191*0fca6ea1SDimitry Andric class CustomRenderer : public OperandRenderer {
2192*0fca6ea1SDimitry Andric protected:
2193*0fca6ea1SDimitry Andric   unsigned InsnID;
2194*0fca6ea1SDimitry Andric   const Record &Renderer;
2195*0fca6ea1SDimitry Andric   /// The name of the operand.
2196*0fca6ea1SDimitry Andric   const std::string SymbolicName;
2197*0fca6ea1SDimitry Andric 
2198*0fca6ea1SDimitry Andric public:
2199*0fca6ea1SDimitry Andric   CustomRenderer(unsigned InsnID, const Record &Renderer,
2200*0fca6ea1SDimitry Andric                  StringRef SymbolicName)
2201*0fca6ea1SDimitry Andric       : OperandRenderer(OR_Custom), InsnID(InsnID), Renderer(Renderer),
2202*0fca6ea1SDimitry Andric         SymbolicName(SymbolicName) {}
2203*0fca6ea1SDimitry Andric 
2204*0fca6ea1SDimitry Andric   static bool classof(const OperandRenderer *R) {
2205*0fca6ea1SDimitry Andric     return R->getKind() == OR_Custom;
2206*0fca6ea1SDimitry Andric   }
2207*0fca6ea1SDimitry Andric 
2208*0fca6ea1SDimitry Andric   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2209*0fca6ea1SDimitry Andric };
2210*0fca6ea1SDimitry Andric 
2211*0fca6ea1SDimitry Andric class CustomOperandRenderer : public OperandRenderer {
2212*0fca6ea1SDimitry Andric protected:
2213*0fca6ea1SDimitry Andric   unsigned InsnID;
2214*0fca6ea1SDimitry Andric   const Record &Renderer;
2215*0fca6ea1SDimitry Andric   /// The name of the operand.
2216*0fca6ea1SDimitry Andric   const std::string SymbolicName;
2217*0fca6ea1SDimitry Andric 
2218*0fca6ea1SDimitry Andric public:
2219*0fca6ea1SDimitry Andric   CustomOperandRenderer(unsigned InsnID, const Record &Renderer,
2220*0fca6ea1SDimitry Andric                         StringRef SymbolicName)
2221*0fca6ea1SDimitry Andric       : OperandRenderer(OR_CustomOperand), InsnID(InsnID), Renderer(Renderer),
2222*0fca6ea1SDimitry Andric         SymbolicName(SymbolicName) {}
2223*0fca6ea1SDimitry Andric 
2224*0fca6ea1SDimitry Andric   static bool classof(const OperandRenderer *R) {
2225*0fca6ea1SDimitry Andric     return R->getKind() == OR_CustomOperand;
2226*0fca6ea1SDimitry Andric   }
2227*0fca6ea1SDimitry Andric 
2228*0fca6ea1SDimitry Andric   void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2229*0fca6ea1SDimitry Andric };
2230*0fca6ea1SDimitry Andric 
2231*0fca6ea1SDimitry Andric /// An action taken when all Matcher predicates succeeded for a parent rule.
2232*0fca6ea1SDimitry Andric ///
2233*0fca6ea1SDimitry Andric /// Typical actions include:
2234*0fca6ea1SDimitry Andric /// * Changing the opcode of an instruction.
2235*0fca6ea1SDimitry Andric /// * Adding an operand to an instruction.
2236*0fca6ea1SDimitry Andric class MatchAction {
2237*0fca6ea1SDimitry Andric public:
2238*0fca6ea1SDimitry Andric   enum ActionKind {
2239*0fca6ea1SDimitry Andric     AK_DebugComment,
2240*0fca6ea1SDimitry Andric     AK_BuildMI,
2241*0fca6ea1SDimitry Andric     AK_BuildConstantMI,
2242*0fca6ea1SDimitry Andric     AK_EraseInst,
2243*0fca6ea1SDimitry Andric     AK_ReplaceReg,
2244*0fca6ea1SDimitry Andric     AK_ConstraintOpsToDef,
2245*0fca6ea1SDimitry Andric     AK_ConstraintOpsToRC,
2246*0fca6ea1SDimitry Andric     AK_MakeTempReg,
2247*0fca6ea1SDimitry Andric   };
2248*0fca6ea1SDimitry Andric 
2249*0fca6ea1SDimitry Andric   MatchAction(ActionKind K) : Kind(K) {}
2250*0fca6ea1SDimitry Andric 
2251*0fca6ea1SDimitry Andric   ActionKind getKind() const { return Kind; }
2252*0fca6ea1SDimitry Andric 
2253*0fca6ea1SDimitry Andric   virtual ~MatchAction() {}
2254*0fca6ea1SDimitry Andric 
2255*0fca6ea1SDimitry Andric   // Some actions may need to add extra predicates to ensure they can run.
2256*0fca6ea1SDimitry Andric   virtual void emitAdditionalPredicates(MatchTable &Table,
2257*0fca6ea1SDimitry Andric                                         RuleMatcher &Rule) const {}
2258*0fca6ea1SDimitry Andric 
2259*0fca6ea1SDimitry Andric   /// Emit the MatchTable opcodes to implement the action.
2260*0fca6ea1SDimitry Andric   virtual void emitActionOpcodes(MatchTable &Table,
2261*0fca6ea1SDimitry Andric                                  RuleMatcher &Rule) const = 0;
2262*0fca6ea1SDimitry Andric 
2263*0fca6ea1SDimitry Andric   /// If this opcode has an overload that can call GIR_Done directly, emit that
2264*0fca6ea1SDimitry Andric   /// instead of the usual opcode and return "true". Return "false" if GIR_Done
2265*0fca6ea1SDimitry Andric   /// still needs to be emitted.
2266*0fca6ea1SDimitry Andric   virtual bool emitActionOpcodesAndDone(MatchTable &Table,
2267*0fca6ea1SDimitry Andric                                         RuleMatcher &Rule) const {
2268*0fca6ea1SDimitry Andric     emitActionOpcodes(Table, Rule);
2269*0fca6ea1SDimitry Andric     return false;
2270*0fca6ea1SDimitry Andric   }
2271*0fca6ea1SDimitry Andric 
2272*0fca6ea1SDimitry Andric private:
2273*0fca6ea1SDimitry Andric   ActionKind Kind;
2274*0fca6ea1SDimitry Andric };
2275*0fca6ea1SDimitry Andric 
2276*0fca6ea1SDimitry Andric /// Generates a comment describing the matched rule being acted upon.
2277*0fca6ea1SDimitry Andric class DebugCommentAction : public MatchAction {
2278*0fca6ea1SDimitry Andric private:
2279*0fca6ea1SDimitry Andric   std::string S;
2280*0fca6ea1SDimitry Andric 
2281*0fca6ea1SDimitry Andric public:
2282*0fca6ea1SDimitry Andric   DebugCommentAction(StringRef S)
2283*0fca6ea1SDimitry Andric       : MatchAction(AK_DebugComment), S(std::string(S)) {}
2284*0fca6ea1SDimitry Andric 
2285*0fca6ea1SDimitry Andric   static bool classof(const MatchAction *A) {
2286*0fca6ea1SDimitry Andric     return A->getKind() == AK_DebugComment;
2287*0fca6ea1SDimitry Andric   }
2288*0fca6ea1SDimitry Andric 
2289*0fca6ea1SDimitry Andric   void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
2290*0fca6ea1SDimitry Andric     Table << MatchTable::Comment(S) << MatchTable::LineBreak;
2291*0fca6ea1SDimitry Andric   }
2292*0fca6ea1SDimitry Andric };
2293*0fca6ea1SDimitry Andric 
2294*0fca6ea1SDimitry Andric /// Generates code to build an instruction or mutate an existing instruction
2295*0fca6ea1SDimitry Andric /// into the desired instruction when this is possible.
2296*0fca6ea1SDimitry Andric class BuildMIAction : public MatchAction {
2297*0fca6ea1SDimitry Andric private:
2298*0fca6ea1SDimitry Andric   unsigned InsnID;
2299*0fca6ea1SDimitry Andric   const CodeGenInstruction *I;
2300*0fca6ea1SDimitry Andric   InstructionMatcher *Matched;
2301*0fca6ea1SDimitry Andric   std::vector<std::unique_ptr<OperandRenderer>> OperandRenderers;
2302*0fca6ea1SDimitry Andric   SmallPtrSet<Record *, 4> DeadImplicitDefs;
2303*0fca6ea1SDimitry Andric 
2304*0fca6ea1SDimitry Andric   std::vector<const InstructionMatcher *> CopiedFlags;
2305*0fca6ea1SDimitry Andric   std::vector<StringRef> SetFlags;
2306*0fca6ea1SDimitry Andric   std::vector<StringRef> UnsetFlags;
2307*0fca6ea1SDimitry Andric 
2308*0fca6ea1SDimitry Andric   /// True if the instruction can be built solely by mutating the opcode.
2309*0fca6ea1SDimitry Andric   bool canMutate(RuleMatcher &Rule, const InstructionMatcher *Insn) const;
2310*0fca6ea1SDimitry Andric 
2311*0fca6ea1SDimitry Andric public:
2312*0fca6ea1SDimitry Andric   BuildMIAction(unsigned InsnID, const CodeGenInstruction *I)
2313*0fca6ea1SDimitry Andric       : MatchAction(AK_BuildMI), InsnID(InsnID), I(I), Matched(nullptr) {}
2314*0fca6ea1SDimitry Andric 
2315*0fca6ea1SDimitry Andric   static bool classof(const MatchAction *A) {
2316*0fca6ea1SDimitry Andric     return A->getKind() == AK_BuildMI;
2317*0fca6ea1SDimitry Andric   }
2318*0fca6ea1SDimitry Andric 
2319*0fca6ea1SDimitry Andric   unsigned getInsnID() const { return InsnID; }
2320*0fca6ea1SDimitry Andric   const CodeGenInstruction *getCGI() const { return I; }
2321*0fca6ea1SDimitry Andric 
2322*0fca6ea1SDimitry Andric   void addSetMIFlags(StringRef Flag) { SetFlags.push_back(Flag); }
2323*0fca6ea1SDimitry Andric   void addUnsetMIFlags(StringRef Flag) { UnsetFlags.push_back(Flag); }
2324*0fca6ea1SDimitry Andric   void addCopiedMIFlags(const InstructionMatcher &IM) {
2325*0fca6ea1SDimitry Andric     CopiedFlags.push_back(&IM);
2326*0fca6ea1SDimitry Andric   }
2327*0fca6ea1SDimitry Andric 
2328*0fca6ea1SDimitry Andric   void chooseInsnToMutate(RuleMatcher &Rule);
2329*0fca6ea1SDimitry Andric 
2330*0fca6ea1SDimitry Andric   void setDeadImplicitDef(Record *R) { DeadImplicitDefs.insert(R); }
2331*0fca6ea1SDimitry Andric 
2332*0fca6ea1SDimitry Andric   template <class Kind, class... Args> Kind &addRenderer(Args &&...args) {
2333*0fca6ea1SDimitry Andric     OperandRenderers.emplace_back(
2334*0fca6ea1SDimitry Andric         std::make_unique<Kind>(InsnID, std::forward<Args>(args)...));
2335*0fca6ea1SDimitry Andric     return *static_cast<Kind *>(OperandRenderers.back().get());
2336*0fca6ea1SDimitry Andric   }
2337*0fca6ea1SDimitry Andric 
2338*0fca6ea1SDimitry Andric   void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2339*0fca6ea1SDimitry Andric };
2340*0fca6ea1SDimitry Andric 
2341*0fca6ea1SDimitry Andric /// Generates code to create a constant that defines a TempReg.
2342*0fca6ea1SDimitry Andric /// The instruction created is usually a G_CONSTANT but it could also be a
2343*0fca6ea1SDimitry Andric /// G_BUILD_VECTOR for vector types.
2344*0fca6ea1SDimitry Andric class BuildConstantAction : public MatchAction {
2345*0fca6ea1SDimitry Andric   unsigned TempRegID;
2346*0fca6ea1SDimitry Andric   int64_t Val;
2347*0fca6ea1SDimitry Andric 
2348*0fca6ea1SDimitry Andric public:
2349*0fca6ea1SDimitry Andric   BuildConstantAction(unsigned TempRegID, int64_t Val)
2350*0fca6ea1SDimitry Andric       : MatchAction(AK_BuildConstantMI), TempRegID(TempRegID), Val(Val) {}
2351*0fca6ea1SDimitry Andric 
2352*0fca6ea1SDimitry Andric   static bool classof(const MatchAction *A) {
2353*0fca6ea1SDimitry Andric     return A->getKind() == AK_BuildConstantMI;
2354*0fca6ea1SDimitry Andric   }
2355*0fca6ea1SDimitry Andric 
2356*0fca6ea1SDimitry Andric   void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2357*0fca6ea1SDimitry Andric };
2358*0fca6ea1SDimitry Andric 
2359*0fca6ea1SDimitry Andric class EraseInstAction : public MatchAction {
2360*0fca6ea1SDimitry Andric   unsigned InsnID;
2361*0fca6ea1SDimitry Andric 
2362*0fca6ea1SDimitry Andric public:
2363*0fca6ea1SDimitry Andric   EraseInstAction(unsigned InsnID)
2364*0fca6ea1SDimitry Andric       : MatchAction(AK_EraseInst), InsnID(InsnID) {}
2365*0fca6ea1SDimitry Andric 
2366*0fca6ea1SDimitry Andric   unsigned getInsnID() const { return InsnID; }
2367*0fca6ea1SDimitry Andric 
2368*0fca6ea1SDimitry Andric   static bool classof(const MatchAction *A) {
2369*0fca6ea1SDimitry Andric     return A->getKind() == AK_EraseInst;
2370*0fca6ea1SDimitry Andric   }
2371*0fca6ea1SDimitry Andric 
2372*0fca6ea1SDimitry Andric   void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2373*0fca6ea1SDimitry Andric   bool emitActionOpcodesAndDone(MatchTable &Table,
2374*0fca6ea1SDimitry Andric                                 RuleMatcher &Rule) const override;
2375*0fca6ea1SDimitry Andric };
2376*0fca6ea1SDimitry Andric 
2377*0fca6ea1SDimitry Andric class ReplaceRegAction : public MatchAction {
2378*0fca6ea1SDimitry Andric   unsigned OldInsnID, OldOpIdx;
2379*0fca6ea1SDimitry Andric   unsigned NewInsnId = -1, NewOpIdx;
2380*0fca6ea1SDimitry Andric   unsigned TempRegID = -1;
2381*0fca6ea1SDimitry Andric 
2382*0fca6ea1SDimitry Andric public:
2383*0fca6ea1SDimitry Andric   ReplaceRegAction(unsigned OldInsnID, unsigned OldOpIdx, unsigned NewInsnId,
2384*0fca6ea1SDimitry Andric                    unsigned NewOpIdx)
2385*0fca6ea1SDimitry Andric       : MatchAction(AK_ReplaceReg), OldInsnID(OldInsnID), OldOpIdx(OldOpIdx),
2386*0fca6ea1SDimitry Andric         NewInsnId(NewInsnId), NewOpIdx(NewOpIdx) {}
2387*0fca6ea1SDimitry Andric 
2388*0fca6ea1SDimitry Andric   ReplaceRegAction(unsigned OldInsnID, unsigned OldOpIdx, unsigned TempRegID)
2389*0fca6ea1SDimitry Andric       : MatchAction(AK_ReplaceReg), OldInsnID(OldInsnID), OldOpIdx(OldOpIdx),
2390*0fca6ea1SDimitry Andric         TempRegID(TempRegID) {}
2391*0fca6ea1SDimitry Andric 
2392*0fca6ea1SDimitry Andric   static bool classof(const MatchAction *A) {
2393*0fca6ea1SDimitry Andric     return A->getKind() == AK_ReplaceReg;
2394*0fca6ea1SDimitry Andric   }
2395*0fca6ea1SDimitry Andric 
2396*0fca6ea1SDimitry Andric   void emitAdditionalPredicates(MatchTable &Table,
2397*0fca6ea1SDimitry Andric                                 RuleMatcher &Rule) const override;
2398*0fca6ea1SDimitry Andric   void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2399*0fca6ea1SDimitry Andric };
2400*0fca6ea1SDimitry Andric 
2401*0fca6ea1SDimitry Andric /// Generates code to constrain the operands of an output instruction to the
2402*0fca6ea1SDimitry Andric /// register classes specified by the definition of that instruction.
2403*0fca6ea1SDimitry Andric class ConstrainOperandsToDefinitionAction : public MatchAction {
2404*0fca6ea1SDimitry Andric   unsigned InsnID;
2405*0fca6ea1SDimitry Andric 
2406*0fca6ea1SDimitry Andric public:
2407*0fca6ea1SDimitry Andric   ConstrainOperandsToDefinitionAction(unsigned InsnID)
2408*0fca6ea1SDimitry Andric       : MatchAction(AK_ConstraintOpsToDef), InsnID(InsnID) {}
2409*0fca6ea1SDimitry Andric 
2410*0fca6ea1SDimitry Andric   static bool classof(const MatchAction *A) {
2411*0fca6ea1SDimitry Andric     return A->getKind() == AK_ConstraintOpsToDef;
2412*0fca6ea1SDimitry Andric   }
2413*0fca6ea1SDimitry Andric 
2414*0fca6ea1SDimitry Andric   void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
2415*0fca6ea1SDimitry Andric     if (InsnID == 0) {
2416*0fca6ea1SDimitry Andric       Table << MatchTable::Opcode("GIR_RootConstrainSelectedInstOperands")
2417*0fca6ea1SDimitry Andric             << MatchTable::LineBreak;
2418*0fca6ea1SDimitry Andric     } else {
2419*0fca6ea1SDimitry Andric       Table << MatchTable::Opcode("GIR_ConstrainSelectedInstOperands")
2420*0fca6ea1SDimitry Andric             << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
2421*0fca6ea1SDimitry Andric             << MatchTable::LineBreak;
2422*0fca6ea1SDimitry Andric     }
2423*0fca6ea1SDimitry Andric   }
2424*0fca6ea1SDimitry Andric };
2425*0fca6ea1SDimitry Andric 
2426*0fca6ea1SDimitry Andric /// Generates code to constrain the specified operand of an output instruction
2427*0fca6ea1SDimitry Andric /// to the specified register class.
2428*0fca6ea1SDimitry Andric class ConstrainOperandToRegClassAction : public MatchAction {
2429*0fca6ea1SDimitry Andric   unsigned InsnID;
2430*0fca6ea1SDimitry Andric   unsigned OpIdx;
2431*0fca6ea1SDimitry Andric   const CodeGenRegisterClass &RC;
2432*0fca6ea1SDimitry Andric 
2433*0fca6ea1SDimitry Andric public:
2434*0fca6ea1SDimitry Andric   ConstrainOperandToRegClassAction(unsigned InsnID, unsigned OpIdx,
2435*0fca6ea1SDimitry Andric                                    const CodeGenRegisterClass &RC)
2436*0fca6ea1SDimitry Andric       : MatchAction(AK_ConstraintOpsToRC), InsnID(InsnID), OpIdx(OpIdx),
2437*0fca6ea1SDimitry Andric         RC(RC) {}
2438*0fca6ea1SDimitry Andric 
2439*0fca6ea1SDimitry Andric   static bool classof(const MatchAction *A) {
2440*0fca6ea1SDimitry Andric     return A->getKind() == AK_ConstraintOpsToRC;
2441*0fca6ea1SDimitry Andric   }
2442*0fca6ea1SDimitry Andric 
2443*0fca6ea1SDimitry Andric   void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2444*0fca6ea1SDimitry Andric };
2445*0fca6ea1SDimitry Andric 
2446*0fca6ea1SDimitry Andric /// Generates code to create a temporary register which can be used to chain
2447*0fca6ea1SDimitry Andric /// instructions together.
2448*0fca6ea1SDimitry Andric class MakeTempRegisterAction : public MatchAction {
2449*0fca6ea1SDimitry Andric private:
2450*0fca6ea1SDimitry Andric   LLTCodeGenOrTempType Ty;
2451*0fca6ea1SDimitry Andric   unsigned TempRegID;
2452*0fca6ea1SDimitry Andric 
2453*0fca6ea1SDimitry Andric public:
2454*0fca6ea1SDimitry Andric   MakeTempRegisterAction(const LLTCodeGenOrTempType &Ty, unsigned TempRegID)
2455*0fca6ea1SDimitry Andric       : MatchAction(AK_MakeTempReg), Ty(Ty), TempRegID(TempRegID) {
2456*0fca6ea1SDimitry Andric     if (Ty.isLLTCodeGen())
2457*0fca6ea1SDimitry Andric       KnownTypes.insert(Ty.getLLTCodeGen());
2458*0fca6ea1SDimitry Andric   }
2459*0fca6ea1SDimitry Andric 
2460*0fca6ea1SDimitry Andric   static bool classof(const MatchAction *A) {
2461*0fca6ea1SDimitry Andric     return A->getKind() == AK_MakeTempReg;
2462*0fca6ea1SDimitry Andric   }
2463*0fca6ea1SDimitry Andric 
2464*0fca6ea1SDimitry Andric   void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;
2465*0fca6ea1SDimitry Andric };
2466*0fca6ea1SDimitry Andric 
2467*0fca6ea1SDimitry Andric } // namespace gi
2468*0fca6ea1SDimitry Andric } // namespace llvm
2469*0fca6ea1SDimitry Andric 
2470*0fca6ea1SDimitry Andric #endif
2471