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