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