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