1 //===- GlobalISelMatchTable.cpp -------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "GlobalISelMatchTable.h"
10 #include "CodeGenInstruction.h"
11 #include "CodeGenRegisters.h"
12 #include "llvm/ADT/Statistic.h"
13 #include "llvm/Support/Debug.h"
14 #include "llvm/Support/LEB128.h"
15 #include "llvm/Support/ScopedPrinter.h"
16 #include "llvm/Support/raw_ostream.h"
17 #include "llvm/TableGen/Error.h"
19 #define DEBUG_TYPE "gi-match-table"
21 STATISTIC(NumPatternEmitted
, "Number of patterns emitted");
28 Error
failUnsupported(const Twine
&Reason
) {
29 return make_error
<StringError
>(Reason
, inconvertibleErrorCode());
32 /// Get the name of the enum value used to number the predicate function.
33 std::string
getEnumNameForPredicate(const TreePredicateFn
&Predicate
) {
34 if (Predicate
.hasGISelPredicateCode())
35 return "GICXXPred_MI_" + Predicate
.getFnName();
36 return "GICXXPred_" + Predicate
.getImmTypeIdentifier().str() + "_" +
37 Predicate
.getFnName();
40 std::string
getMatchOpcodeForImmPredicate(const TreePredicateFn
&Predicate
) {
41 return "GIM_Check" + Predicate
.getImmTypeIdentifier().str() + "ImmPredicate";
45 constexpr StringLiteral EncodeMacroName
= "GIMT_Encode";
49 //===- Helpers ------------------------------------------------------------===//
51 void emitEncodingMacrosDef(raw_ostream
&OS
) {
52 OS
<< "#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__\n"
53 << "#define " << EncodeMacroName
<< "2(Val)"
54 << " uint8_t(Val), uint8_t((uint16_t)Val >> 8)\n"
55 << "#define " << EncodeMacroName
<< "4(Val)"
56 << " uint8_t(Val), uint8_t((uint32_t)Val >> 8), "
57 "uint8_t((uint32_t)Val >> 16), uint8_t((uint32_t)Val >> 24)\n"
58 << "#define " << EncodeMacroName
<< "8(Val)"
59 << " uint8_t(Val), uint8_t((uint64_t)Val >> 8), "
60 "uint8_t((uint64_t)Val >> 16), uint8_t((uint64_t)Val >> 24), "
61 "uint8_t((uint64_t)Val >> 32), uint8_t((uint64_t)Val >> 40), "
62 "uint8_t((uint64_t)Val >> 48), uint8_t((uint64_t)Val >> 56)\n"
64 << "#define " << EncodeMacroName
<< "2(Val)"
65 << " uint8_t((uint16_t)Val >> 8), uint8_t(Val)\n"
66 << "#define " << EncodeMacroName
<< "4(Val)"
67 << " uint8_t((uint32_t)Val >> 24), uint8_t((uint32_t)Val >> 16), "
68 "uint8_t((uint32_t)Val >> 8), uint8_t(Val)\n"
69 << "#define " << EncodeMacroName
<< "8(Val)"
70 << " uint8_t((uint64_t)Val >> 56), uint8_t((uint64_t)Val >> 48), "
71 "uint8_t((uint64_t)Val >> 40), uint8_t((uint64_t)Val >> 32), "
72 "uint8_t((uint64_t)Val >> 24), uint8_t((uint64_t)Val >> 16), "
73 "uint8_t((uint64_t)Val >> 8), uint8_t(Val)\n"
77 void emitEncodingMacrosUndef(raw_ostream
&OS
) {
78 OS
<< "#undef " << EncodeMacroName
<< "2\n"
79 << "#undef " << EncodeMacroName
<< "4\n"
80 << "#undef " << EncodeMacroName
<< "8\n";
83 std::string
getNameForFeatureBitset(const std::vector
<Record
*> &FeatureBitset
,
85 std::string Name
= "GIFBS";
86 for (const auto &Feature
: FeatureBitset
)
87 Name
+= ("_" + Feature
->getName()).str();
89 Name
+= ("_HwMode" + std::to_string(HwModeIdx
));
93 template <class GroupT
>
94 std::vector
<Matcher
*>
95 optimizeRules(ArrayRef
<Matcher
*> Rules
,
96 std::vector
<std::unique_ptr
<Matcher
>> &MatcherStorage
) {
98 std::vector
<Matcher
*> OptRules
;
99 std::unique_ptr
<GroupT
> CurrentGroup
= std::make_unique
<GroupT
>();
100 assert(CurrentGroup
->empty() && "Newly created group isn't empty!");
101 unsigned NumGroups
= 0;
103 auto ProcessCurrentGroup
= [&]() {
104 if (CurrentGroup
->empty())
105 // An empty group is good to be reused:
108 // If the group isn't large enough to provide any benefit, move all the
109 // added rules out of it and make sure to re-create the group to properly
111 if (CurrentGroup
->size() < 2)
112 append_range(OptRules
, CurrentGroup
->matchers());
114 CurrentGroup
->finalize();
115 OptRules
.push_back(CurrentGroup
.get());
116 MatcherStorage
.emplace_back(std::move(CurrentGroup
));
119 CurrentGroup
= std::make_unique
<GroupT
>();
121 for (Matcher
*Rule
: Rules
) {
122 // Greedily add as many matchers as possible to the current group:
123 if (CurrentGroup
->addMatcher(*Rule
))
126 ProcessCurrentGroup();
127 assert(CurrentGroup
->empty() && "A group wasn't properly re-initialized");
129 // Try to add the pending matcher to a newly created empty group:
130 if (!CurrentGroup
->addMatcher(*Rule
))
131 // If we couldn't add the matcher to an empty group, that group type
132 // doesn't support that kind of matchers at all, so just skip it:
133 OptRules
.push_back(Rule
);
135 ProcessCurrentGroup();
137 LLVM_DEBUG(dbgs() << "NumGroups: " << NumGroups
<< "\n");
139 assert(CurrentGroup
->empty() && "The last group wasn't properly processed");
143 template std::vector
<Matcher
*> optimizeRules
<GroupMatcher
>(
144 ArrayRef
<Matcher
*> Rules
,
145 std::vector
<std::unique_ptr
<Matcher
>> &MatcherStorage
);
147 template std::vector
<Matcher
*> optimizeRules
<SwitchMatcher
>(
148 ArrayRef
<Matcher
*> Rules
,
149 std::vector
<std::unique_ptr
<Matcher
>> &MatcherStorage
);
151 static std::string
getEncodedEmitStr(StringRef NamedValue
, unsigned NumBytes
) {
152 if (NumBytes
== 2 || NumBytes
== 4 || NumBytes
== 8)
153 return (EncodeMacroName
+ Twine(NumBytes
) + "(" + NamedValue
+ ")").str();
154 llvm_unreachable("Unsupported number of bytes!");
157 //===- Global Data --------------------------------------------------------===//
159 std::set
<LLTCodeGen
> KnownTypes
;
161 //===- MatchTableRecord ---------------------------------------------------===//
163 void MatchTableRecord::emit(raw_ostream
&OS
, bool LineBreakIsNextAfterThis
,
164 const MatchTable
&Table
) const {
165 bool UseLineComment
=
166 LineBreakIsNextAfterThis
|| (Flags
& MTRF_LineBreakFollows
);
167 if (Flags
& (MTRF_JumpTarget
| MTRF_CommaFollows
))
168 UseLineComment
= false;
170 if (Flags
& MTRF_Comment
)
171 OS
<< (UseLineComment
? "// " : "/*");
173 if (NumElements
> 1 && !(Flags
& (MTRF_PreEncoded
| MTRF_Comment
)))
174 OS
<< getEncodedEmitStr(EmitStr
, NumElements
);
178 if (Flags
& MTRF_Label
)
179 OS
<< ": @" << Table
.getLabelIndex(LabelID
);
181 if ((Flags
& MTRF_Comment
) && !UseLineComment
)
184 if (Flags
& MTRF_JumpTarget
) {
185 if (Flags
& MTRF_Comment
)
187 // TODO: Could encode this AOT to speed up build of generated file
188 OS
<< getEncodedEmitStr(llvm::to_string(Table
.getLabelIndex(LabelID
)),
192 if (Flags
& MTRF_CommaFollows
) {
194 if (!LineBreakIsNextAfterThis
&& !(Flags
& MTRF_LineBreakFollows
))
198 if (Flags
& MTRF_LineBreakFollows
)
202 //===- MatchTable ---------------------------------------------------------===//
204 MatchTableRecord
MatchTable::LineBreak
= {
205 std::nullopt
, "" /* Emit String */, 0 /* Elements */,
206 MatchTableRecord::MTRF_LineBreakFollows
};
208 MatchTableRecord
MatchTable::Comment(StringRef Comment
) {
209 return MatchTableRecord(std::nullopt
, Comment
, 0,
210 MatchTableRecord::MTRF_Comment
);
213 MatchTableRecord
MatchTable::Opcode(StringRef Opcode
, int IndentAdjust
) {
214 unsigned ExtraFlags
= 0;
215 if (IndentAdjust
> 0)
216 ExtraFlags
|= MatchTableRecord::MTRF_Indent
;
217 if (IndentAdjust
< 0)
218 ExtraFlags
|= MatchTableRecord::MTRF_Outdent
;
220 return MatchTableRecord(std::nullopt
, Opcode
, 1,
221 MatchTableRecord::MTRF_CommaFollows
| ExtraFlags
);
224 MatchTableRecord
MatchTable::NamedValue(unsigned NumBytes
,
225 StringRef NamedValue
) {
226 return MatchTableRecord(std::nullopt
, NamedValue
, NumBytes
,
227 MatchTableRecord::MTRF_CommaFollows
);
230 MatchTableRecord
MatchTable::NamedValue(unsigned NumBytes
, StringRef NamedValue
,
232 return MatchTableRecord(std::nullopt
, NamedValue
, NumBytes
,
233 MatchTableRecord::MTRF_CommaFollows
, RawValue
);
236 MatchTableRecord
MatchTable::NamedValue(unsigned NumBytes
, StringRef Namespace
,
237 StringRef NamedValue
) {
238 return MatchTableRecord(std::nullopt
, (Namespace
+ "::" + NamedValue
).str(),
239 NumBytes
, MatchTableRecord::MTRF_CommaFollows
);
242 MatchTableRecord
MatchTable::NamedValue(unsigned NumBytes
, StringRef Namespace
,
243 StringRef NamedValue
,
245 return MatchTableRecord(std::nullopt
, (Namespace
+ "::" + NamedValue
).str(),
246 NumBytes
, MatchTableRecord::MTRF_CommaFollows
,
250 MatchTableRecord
MatchTable::IntValue(unsigned NumBytes
, int64_t IntValue
) {
251 assert(isUIntN(NumBytes
* 8, IntValue
) || isIntN(NumBytes
* 8, IntValue
));
252 auto Str
= llvm::to_string(IntValue
);
253 if (NumBytes
== 1 && IntValue
< 0)
254 Str
= "uint8_t(" + Str
+ ")";
255 // TODO: Could optimize this directly to save the compiler some work when
257 return MatchTableRecord(std::nullopt
, Str
, NumBytes
,
258 MatchTableRecord::MTRF_CommaFollows
);
261 MatchTableRecord
MatchTable::ULEB128Value(uint64_t IntValue
) {
263 unsigned Len
= encodeULEB128(IntValue
, Buffer
);
265 // Simple case (most common)
267 return MatchTableRecord(std::nullopt
, llvm::to_string((unsigned)Buffer
[0]),
268 1, MatchTableRecord::MTRF_CommaFollows
);
271 // Print it as, e.g. /* -123456 (*/, 0xC0, 0xBB, 0x78 /*)*/
273 raw_string_ostream
OS(Str
);
274 OS
<< "/* " << llvm::to_string(IntValue
) << "(*/";
275 for (unsigned K
= 0; K
< Len
; ++K
) {
278 OS
<< "0x" << llvm::toHex({Buffer
[K
]});
281 return MatchTableRecord(std::nullopt
, Str
, Len
,
282 MatchTableRecord::MTRF_CommaFollows
|
283 MatchTableRecord::MTRF_PreEncoded
);
286 MatchTableRecord
MatchTable::Label(unsigned LabelID
) {
287 return MatchTableRecord(LabelID
, "Label " + llvm::to_string(LabelID
), 0,
288 MatchTableRecord::MTRF_Label
|
289 MatchTableRecord::MTRF_Comment
|
290 MatchTableRecord::MTRF_LineBreakFollows
);
293 MatchTableRecord
MatchTable::JumpTarget(unsigned LabelID
) {
294 return MatchTableRecord(LabelID
, "Label " + llvm::to_string(LabelID
), 4,
295 MatchTableRecord::MTRF_JumpTarget
|
296 MatchTableRecord::MTRF_Comment
|
297 MatchTableRecord::MTRF_CommaFollows
);
300 void MatchTable::emitUse(raw_ostream
&OS
) const { OS
<< "MatchTable" << ID
; }
302 void MatchTable::emitDeclaration(raw_ostream
&OS
) const {
303 unsigned Indentation
= 4;
304 OS
<< " constexpr static uint8_t MatchTable" << ID
<< "[] = {";
305 LineBreak
.emit(OS
, true, *this);
306 OS
<< std::string(Indentation
, ' ');
308 for (auto I
= Contents
.begin(), E
= Contents
.end(); I
!= E
; ++I
) {
309 bool LineBreakIsNext
= false;
310 const auto &NextI
= std::next(I
);
313 if (NextI
->EmitStr
== "" &&
314 NextI
->Flags
== MatchTableRecord::MTRF_LineBreakFollows
)
315 LineBreakIsNext
= true;
318 if (I
->Flags
& MatchTableRecord::MTRF_Indent
)
321 I
->emit(OS
, LineBreakIsNext
, *this);
322 if (I
->Flags
& MatchTableRecord::MTRF_LineBreakFollows
)
323 OS
<< std::string(Indentation
, ' ');
325 if (I
->Flags
& MatchTableRecord::MTRF_Outdent
)
328 OS
<< "}; // Size: " << CurrentSize
<< " bytes\n";
331 MatchTable
MatchTable::buildTable(ArrayRef
<Matcher
*> Rules
, bool WithCoverage
,
333 MatchTable
Table(WithCoverage
, IsCombiner
);
334 for (Matcher
*Rule
: Rules
)
337 return Table
<< MatchTable::Opcode("GIM_Reject") << MatchTable::LineBreak
;
340 //===- LLTCodeGen ---------------------------------------------------------===//
342 std::string
LLTCodeGen::getCxxEnumValue() const {
344 raw_string_ostream
OS(Str
);
346 emitCxxEnumValue(OS
);
350 void LLTCodeGen::emitCxxEnumValue(raw_ostream
&OS
) const {
352 OS
<< "GILLT_s" << Ty
.getSizeInBits();
356 OS
<< (Ty
.isScalable() ? "GILLT_nxv" : "GILLT_v")
357 << Ty
.getElementCount().getKnownMinValue() << "s"
358 << Ty
.getScalarSizeInBits();
361 if (Ty
.isPointer()) {
362 OS
<< "GILLT_p" << Ty
.getAddressSpace();
363 if (Ty
.getSizeInBits() > 0)
364 OS
<< "s" << Ty
.getSizeInBits();
367 llvm_unreachable("Unhandled LLT");
370 void LLTCodeGen::emitCxxConstructorCall(raw_ostream
&OS
) const {
372 OS
<< "LLT::scalar(" << Ty
.getSizeInBits() << ")";
377 << (Ty
.isScalable() ? "ElementCount::getScalable("
378 : "ElementCount::getFixed(")
379 << Ty
.getElementCount().getKnownMinValue() << "), "
380 << Ty
.getScalarSizeInBits() << ")";
383 if (Ty
.isPointer() && Ty
.getSizeInBits() > 0) {
384 OS
<< "LLT::pointer(" << Ty
.getAddressSpace() << ", " << Ty
.getSizeInBits()
388 llvm_unreachable("Unhandled LLT");
391 /// This ordering is used for std::unique() and llvm::sort(). There's no
392 /// particular logic behind the order but either A < B or B < A must be
394 bool LLTCodeGen::operator<(const LLTCodeGen
&Other
) const {
395 if (Ty
.isValid() != Other
.Ty
.isValid())
396 return Ty
.isValid() < Other
.Ty
.isValid();
400 if (Ty
.isVector() != Other
.Ty
.isVector())
401 return Ty
.isVector() < Other
.Ty
.isVector();
402 if (Ty
.isScalar() != Other
.Ty
.isScalar())
403 return Ty
.isScalar() < Other
.Ty
.isScalar();
404 if (Ty
.isPointer() != Other
.Ty
.isPointer())
405 return Ty
.isPointer() < Other
.Ty
.isPointer();
407 if (Ty
.isPointer() && Ty
.getAddressSpace() != Other
.Ty
.getAddressSpace())
408 return Ty
.getAddressSpace() < Other
.Ty
.getAddressSpace();
410 if (Ty
.isVector() && Ty
.getElementCount() != Other
.Ty
.getElementCount())
411 return std::make_tuple(Ty
.isScalable(),
412 Ty
.getElementCount().getKnownMinValue()) <
413 std::make_tuple(Other
.Ty
.isScalable(),
414 Other
.Ty
.getElementCount().getKnownMinValue());
416 assert((!Ty
.isVector() || Ty
.isScalable() == Other
.Ty
.isScalable()) &&
417 "Unexpected mismatch of scalable property");
419 ? std::make_tuple(Ty
.isScalable(),
420 Ty
.getSizeInBits().getKnownMinValue()) <
421 std::make_tuple(Other
.Ty
.isScalable(),
422 Other
.Ty
.getSizeInBits().getKnownMinValue())
423 : Ty
.getSizeInBits().getFixedValue() <
424 Other
.Ty
.getSizeInBits().getFixedValue();
427 //===- LLTCodeGen Helpers -------------------------------------------------===//
429 std::optional
<LLTCodeGen
> MVTToLLT(MVT::SimpleValueType SVT
) {
432 if (VT
.isVector() && !VT
.getVectorElementCount().isScalar())
434 LLT::vector(VT
.getVectorElementCount(), VT
.getScalarSizeInBits()));
436 if (VT
.isInteger() || VT
.isFloatingPoint())
437 return LLTCodeGen(LLT::scalar(VT
.getSizeInBits()));
442 //===- Matcher ------------------------------------------------------------===//
444 void Matcher::optimize() {}
446 Matcher::~Matcher() {}
448 //===- GroupMatcher -------------------------------------------------------===//
450 bool GroupMatcher::candidateConditionMatches(
451 const PredicateMatcher
&Predicate
) const {
454 // Sharing predicates for nested instructions is not supported yet as we
455 // currently don't hoist the GIM_RecordInsn's properly, therefore we can
456 // only work on the original root instruction (InsnVarID == 0):
457 if (Predicate
.getInsnVarID() != 0)
459 // ... otherwise an empty group can handle any predicate with no specific
464 const Matcher
&Representative
= **Matchers
.begin();
465 const auto &RepresentativeCondition
= Representative
.getFirstCondition();
466 // ... if not empty, the group can only accomodate matchers with the exact
467 // same first condition:
468 return Predicate
.isIdentical(RepresentativeCondition
);
471 bool GroupMatcher::addMatcher(Matcher
&Candidate
) {
472 if (!Candidate
.hasFirstCondition())
475 const PredicateMatcher
&Predicate
= Candidate
.getFirstCondition();
476 if (!candidateConditionMatches(Predicate
))
479 Matchers
.push_back(&Candidate
);
483 void GroupMatcher::finalize() {
484 assert(Conditions
.empty() && "Already finalized?");
488 Matcher
&FirstRule
= **Matchers
.begin();
490 // All the checks are expected to succeed during the first iteration:
491 for (const auto &Rule
: Matchers
)
492 if (!Rule
->hasFirstCondition())
494 const auto &FirstCondition
= FirstRule
.getFirstCondition();
495 for (unsigned I
= 1, E
= Matchers
.size(); I
< E
; ++I
)
496 if (!Matchers
[I
]->getFirstCondition().isIdentical(FirstCondition
))
499 Conditions
.push_back(FirstRule
.popFirstCondition());
500 for (unsigned I
= 1, E
= Matchers
.size(); I
< E
; ++I
)
501 Matchers
[I
]->popFirstCondition();
505 void GroupMatcher::emit(MatchTable
&Table
) {
506 unsigned LabelID
= ~0U;
507 if (!Conditions
.empty()) {
508 LabelID
= Table
.allocateLabelID();
509 Table
<< MatchTable::Opcode("GIM_Try", +1)
510 << MatchTable::Comment("On fail goto")
511 << MatchTable::JumpTarget(LabelID
) << MatchTable::LineBreak
;
513 for (auto &Condition
: Conditions
)
514 Condition
->emitPredicateOpcodes(
515 Table
, *static_cast<RuleMatcher
*>(*Matchers
.begin()));
517 for (const auto &M
: Matchers
)
521 if (!Conditions
.empty())
522 Table
<< MatchTable::Opcode("GIM_Reject", -1) << MatchTable::LineBreak
523 << MatchTable::Label(LabelID
);
526 void GroupMatcher::optimize() {
527 // Make sure we only sort by a specific predicate within a range of rules that
528 // all have that predicate checked against a specific value (not a wildcard):
529 auto F
= Matchers
.begin();
531 auto E
= Matchers
.end();
534 auto *R
= static_cast<RuleMatcher
*>(*T
);
535 if (!R
->getFirstConditionAsRootType().get().isValid())
539 std::stable_sort(F
, T
, [](Matcher
*A
, Matcher
*B
) {
540 auto *L
= static_cast<RuleMatcher
*>(A
);
541 auto *R
= static_cast<RuleMatcher
*>(B
);
542 return L
->getFirstConditionAsRootType() <
543 R
->getFirstConditionAsRootType();
548 optimizeRules
<GroupMatcher
>(Matchers
, MatcherStorage
).swap(Matchers
);
549 optimizeRules
<SwitchMatcher
>(Matchers
, MatcherStorage
).swap(Matchers
);
552 //===- SwitchMatcher ------------------------------------------------------===//
554 bool SwitchMatcher::isSupportedPredicateType(const PredicateMatcher
&P
) {
555 return isa
<InstructionOpcodeMatcher
>(P
) || isa
<LLTOperandMatcher
>(P
);
558 bool SwitchMatcher::candidateConditionMatches(
559 const PredicateMatcher
&Predicate
) const {
562 // Sharing predicates for nested instructions is not supported yet as we
563 // currently don't hoist the GIM_RecordInsn's properly, therefore we can
564 // only work on the original root instruction (InsnVarID == 0):
565 if (Predicate
.getInsnVarID() != 0)
567 // ... while an attempt to add even a root matcher to an empty SwitchMatcher
568 // could fail as not all the types of conditions are supported:
569 if (!isSupportedPredicateType(Predicate
))
571 // ... or the condition might not have a proper implementation of
572 // getValue() / isIdenticalDownToValue() yet:
573 if (!Predicate
.hasValue())
575 // ... otherwise an empty Switch can accomodate the condition with no
576 // further requirements:
580 const Matcher
&CaseRepresentative
= **Matchers
.begin();
581 const auto &RepresentativeCondition
= CaseRepresentative
.getFirstCondition();
582 // Switch-cases must share the same kind of condition and path to the value it
584 if (!Predicate
.isIdenticalDownToValue(RepresentativeCondition
))
587 const auto Value
= Predicate
.getValue();
588 // ... but be unique with respect to the actual value they check:
589 return Values
.count(Value
) == 0;
592 bool SwitchMatcher::addMatcher(Matcher
&Candidate
) {
593 if (!Candidate
.hasFirstCondition())
596 const PredicateMatcher
&Predicate
= Candidate
.getFirstCondition();
597 if (!candidateConditionMatches(Predicate
))
599 const auto Value
= Predicate
.getValue();
600 Values
.insert(Value
);
602 Matchers
.push_back(&Candidate
);
606 void SwitchMatcher::finalize() {
607 assert(Condition
== nullptr && "Already finalized");
608 assert(Values
.size() == Matchers
.size() && "Broken SwitchMatcher");
612 llvm::stable_sort(Matchers
, [](const Matcher
*L
, const Matcher
*R
) {
613 return L
->getFirstCondition().getValue() <
614 R
->getFirstCondition().getValue();
616 Condition
= Matchers
[0]->popFirstCondition();
617 for (unsigned I
= 1, E
= Values
.size(); I
< E
; ++I
)
618 Matchers
[I
]->popFirstCondition();
621 void SwitchMatcher::emitPredicateSpecificOpcodes(const PredicateMatcher
&P
,
623 assert(isSupportedPredicateType(P
) && "Predicate type is not supported");
625 if (const auto *Condition
= dyn_cast
<InstructionOpcodeMatcher
>(&P
)) {
626 Table
<< MatchTable::Opcode("GIM_SwitchOpcode") << MatchTable::Comment("MI")
627 << MatchTable::ULEB128Value(Condition
->getInsnVarID());
630 if (const auto *Condition
= dyn_cast
<LLTOperandMatcher
>(&P
)) {
631 Table
<< MatchTable::Opcode("GIM_SwitchType") << MatchTable::Comment("MI")
632 << MatchTable::ULEB128Value(Condition
->getInsnVarID())
633 << MatchTable::Comment("Op")
634 << MatchTable::ULEB128Value(Condition
->getOpIdx());
638 llvm_unreachable("emitPredicateSpecificOpcodes is broken: can not handle a "
639 "predicate type that is claimed to be supported");
642 void SwitchMatcher::emit(MatchTable
&Table
) {
643 assert(Values
.size() == Matchers
.size() && "Broken SwitchMatcher");
646 assert(Condition
!= nullptr &&
647 "Broken SwitchMatcher, hasn't been finalized?");
649 std::vector
<unsigned> LabelIDs(Values
.size());
650 std::generate(LabelIDs
.begin(), LabelIDs
.end(),
651 [&Table
]() { return Table
.allocateLabelID(); });
652 const unsigned Default
= Table
.allocateLabelID();
654 const int64_t LowerBound
= Values
.begin()->getRawValue();
655 const int64_t UpperBound
= Values
.rbegin()->getRawValue() + 1;
657 emitPredicateSpecificOpcodes(*Condition
, Table
);
659 Table
<< MatchTable::Comment("[") << MatchTable::IntValue(2, LowerBound
)
660 << MatchTable::IntValue(2, UpperBound
) << MatchTable::Comment(")")
661 << MatchTable::Comment("default:") << MatchTable::JumpTarget(Default
);
663 int64_t J
= LowerBound
;
664 auto VI
= Values
.begin();
665 for (unsigned I
= 0, E
= Values
.size(); I
< E
; ++I
) {
667 while (J
++ < V
.getRawValue())
668 Table
<< MatchTable::IntValue(4, 0);
670 Table
<< MatchTable::LineBreak
<< V
<< MatchTable::JumpTarget(LabelIDs
[I
]);
672 Table
<< MatchTable::LineBreak
;
674 for (unsigned I
= 0, E
= Values
.size(); I
< E
; ++I
) {
675 Table
<< MatchTable::Label(LabelIDs
[I
]);
676 Matchers
[I
]->emit(Table
);
677 Table
<< MatchTable::Opcode("GIM_Reject") << MatchTable::LineBreak
;
679 Table
<< MatchTable::Label(Default
);
682 //===- RuleMatcher --------------------------------------------------------===//
684 uint64_t RuleMatcher::NextRuleID
= 0;
686 StringRef
RuleMatcher::getOpcode() const {
687 return Matchers
.front()->getOpcode();
690 unsigned RuleMatcher::getNumOperands() const {
691 return Matchers
.front()->getNumOperands();
694 LLTCodeGen
RuleMatcher::getFirstConditionAsRootType() {
695 InstructionMatcher
&InsnMatcher
= *Matchers
.front();
696 if (!InsnMatcher
.predicates_empty())
698 dyn_cast
<LLTOperandMatcher
>(&**InsnMatcher
.predicates_begin()))
699 if (TM
->getInsnVarID() == 0 && TM
->getOpIdx() == 0)
704 void RuleMatcher::optimize() {
705 for (auto &Item
: InsnVariableIDs
) {
706 InstructionMatcher
&InsnMatcher
= *Item
.first
;
707 for (auto &OM
: InsnMatcher
.operands()) {
708 // Complex Patterns are usually expensive and they relatively rarely fail
709 // on their own: more often we end up throwing away all the work done by a
710 // matching part of a complex pattern because some other part of the
711 // enclosing pattern didn't match. All of this makes it beneficial to
712 // delay complex patterns until the very end of the rule matching,
713 // especially for targets having lots of complex patterns.
714 for (auto &OP
: OM
->predicates())
715 if (isa
<ComplexPatternOperandMatcher
>(OP
))
716 EpilogueMatchers
.emplace_back(std::move(OP
));
717 OM
->eraseNullPredicates();
719 InsnMatcher
.optimize();
721 llvm::sort(EpilogueMatchers
, [](const std::unique_ptr
<PredicateMatcher
> &L
,
722 const std::unique_ptr
<PredicateMatcher
> &R
) {
723 return std::make_tuple(L
->getKind(), L
->getInsnVarID(), L
->getOpIdx()) <
724 std::make_tuple(R
->getKind(), R
->getInsnVarID(), R
->getOpIdx());
728 bool RuleMatcher::hasFirstCondition() const {
729 if (insnmatchers_empty())
731 InstructionMatcher
&Matcher
= insnmatchers_front();
732 if (!Matcher
.predicates_empty())
734 for (auto &OM
: Matcher
.operands())
735 for (auto &OP
: OM
->predicates())
736 if (!isa
<InstructionOperandMatcher
>(OP
))
741 const PredicateMatcher
&RuleMatcher::getFirstCondition() const {
742 assert(!insnmatchers_empty() &&
743 "Trying to get a condition from an empty RuleMatcher");
745 InstructionMatcher
&Matcher
= insnmatchers_front();
746 if (!Matcher
.predicates_empty())
747 return **Matcher
.predicates_begin();
748 // If there is no more predicate on the instruction itself, look at its
750 for (auto &OM
: Matcher
.operands())
751 for (auto &OP
: OM
->predicates())
752 if (!isa
<InstructionOperandMatcher
>(OP
))
755 llvm_unreachable("Trying to get a condition from an InstructionMatcher with "
759 std::unique_ptr
<PredicateMatcher
> RuleMatcher::popFirstCondition() {
760 assert(!insnmatchers_empty() &&
761 "Trying to pop a condition from an empty RuleMatcher");
763 InstructionMatcher
&Matcher
= insnmatchers_front();
764 if (!Matcher
.predicates_empty())
765 return Matcher
.predicates_pop_front();
766 // If there is no more predicate on the instruction itself, look at its
768 for (auto &OM
: Matcher
.operands())
769 for (auto &OP
: OM
->predicates())
770 if (!isa
<InstructionOperandMatcher
>(OP
)) {
771 std::unique_ptr
<PredicateMatcher
> Result
= std::move(OP
);
772 OM
->eraseNullPredicates();
776 llvm_unreachable("Trying to pop a condition from an InstructionMatcher with "
780 GISelFlags
RuleMatcher::updateGISelFlag(GISelFlags CurFlags
, const Record
*R
,
782 GISelFlags FlagBit
) {
783 // If the value of a flag is unset, ignore it.
784 // If it's set, it always takes precedence over the existing value so
785 // clear/set the corresponding bit.
787 bool Value
= R
->getValueAsBitOrUnset("GIIgnoreCopies", Unset
);
789 return Value
? (CurFlags
| FlagBit
) : (CurFlags
& ~FlagBit
);
793 SaveAndRestore
<GISelFlags
> RuleMatcher::setGISelFlags(const Record
*R
) {
794 if (!R
|| !R
->isSubClassOf("GISelFlags"))
795 return {Flags
, Flags
};
797 assert((R
->isSubClassOf("PatFrags") || R
->isSubClassOf("Pattern")) &&
798 "GISelFlags is only expected on Pattern/PatFrags!");
800 GISelFlags NewFlags
=
801 updateGISelFlag(Flags
, R
, "GIIgnoreCopies", GISF_IgnoreCopies
);
802 return {Flags
, NewFlags
};
805 Error
RuleMatcher::defineComplexSubOperand(StringRef SymbolicName
,
806 Record
*ComplexPattern
,
808 unsigned SubOperandID
,
809 StringRef ParentSymbolicName
) {
810 std::string
ParentName(ParentSymbolicName
);
811 if (ComplexSubOperands
.count(SymbolicName
)) {
812 const std::string
&RecordedParentName
=
813 ComplexSubOperandsParentName
[SymbolicName
];
814 if (RecordedParentName
!= ParentName
)
815 return failUnsupported("Error: Complex suboperand " + SymbolicName
+
816 " referenced by different operands: " +
817 RecordedParentName
+ " and " + ParentName
+ ".");
818 // Complex suboperand referenced more than once from same the operand is
819 // used to generate 'same operand check'. Emitting of
820 // GIR_ComplexSubOperandRenderer for them is already handled.
821 return Error::success();
824 ComplexSubOperands
[SymbolicName
] =
825 std::make_tuple(ComplexPattern
, RendererID
, SubOperandID
);
826 ComplexSubOperandsParentName
[SymbolicName
] = ParentName
;
828 return Error::success();
831 InstructionMatcher
&RuleMatcher::addInstructionMatcher(StringRef SymbolicName
) {
832 Matchers
.emplace_back(new InstructionMatcher(*this, SymbolicName
));
833 MutatableInsns
.insert(Matchers
.back().get());
834 return *Matchers
.back();
837 void RuleMatcher::addRequiredSimplePredicate(StringRef PredName
) {
838 RequiredSimplePredicates
.push_back(PredName
.str());
841 const std::vector
<std::string
> &RuleMatcher::getRequiredSimplePredicates() {
842 return RequiredSimplePredicates
;
845 void RuleMatcher::addRequiredFeature(Record
*Feature
) {
846 RequiredFeatures
.push_back(Feature
);
849 const std::vector
<Record
*> &RuleMatcher::getRequiredFeatures() const {
850 return RequiredFeatures
;
853 unsigned RuleMatcher::implicitlyDefineInsnVar(InstructionMatcher
&Matcher
) {
854 unsigned NewInsnVarID
= NextInsnVarID
++;
855 InsnVariableIDs
[&Matcher
] = NewInsnVarID
;
859 unsigned RuleMatcher::getInsnVarID(InstructionMatcher
&InsnMatcher
) const {
860 const auto &I
= InsnVariableIDs
.find(&InsnMatcher
);
861 if (I
!= InsnVariableIDs
.end())
863 llvm_unreachable("Matched Insn was not captured in a local variable");
866 void RuleMatcher::defineOperand(StringRef SymbolicName
, OperandMatcher
&OM
) {
867 if (!DefinedOperands
.contains(SymbolicName
)) {
868 DefinedOperands
[SymbolicName
] = &OM
;
872 // If the operand is already defined, then we must ensure both references in
873 // the matcher have the exact same node.
874 RuleMatcher
&RM
= OM
.getInstructionMatcher().getRuleMatcher();
875 OM
.addPredicate
<SameOperandMatcher
>(
876 OM
.getSymbolicName(), getOperandMatcher(OM
.getSymbolicName()).getOpIdx(),
880 void RuleMatcher::definePhysRegOperand(Record
*Reg
, OperandMatcher
&OM
) {
881 if (!PhysRegOperands
.contains(Reg
)) {
882 PhysRegOperands
[Reg
] = &OM
;
888 RuleMatcher::getInstructionMatcher(StringRef SymbolicName
) const {
889 for (const auto &I
: InsnVariableIDs
)
890 if (I
.first
->getSymbolicName() == SymbolicName
)
893 ("Failed to lookup instruction " + SymbolicName
).str().c_str());
896 const OperandMatcher
&RuleMatcher::getPhysRegOperandMatcher(Record
*Reg
) const {
897 const auto &I
= PhysRegOperands
.find(Reg
);
899 if (I
== PhysRegOperands
.end()) {
900 PrintFatalError(SrcLoc
, "Register " + Reg
->getName() +
901 " was not declared in matcher");
907 OperandMatcher
&RuleMatcher::getOperandMatcher(StringRef Name
) {
908 const auto &I
= DefinedOperands
.find(Name
);
910 if (I
== DefinedOperands
.end())
911 PrintFatalError(SrcLoc
, "Operand " + Name
+ " was not declared in matcher");
916 const OperandMatcher
&RuleMatcher::getOperandMatcher(StringRef Name
) const {
917 const auto &I
= DefinedOperands
.find(Name
);
919 if (I
== DefinedOperands
.end())
920 PrintFatalError(SrcLoc
, "Operand " + Name
+ " was not declared in matcher");
925 void RuleMatcher::emit(MatchTable
&Table
) {
926 if (Matchers
.empty())
927 llvm_unreachable("Unexpected empty matcher!");
929 // The representation supports rules that require multiple roots such as:
931 // %elt0(s32) = G_LOAD %ptr
932 // %1(p0) = G_ADD %ptr, 4
933 // %elt1(s32) = G_LOAD p0 %1
934 // which could be usefully folded into:
936 // %elt0(s32), %elt1(s32) = TGT_LOAD_PAIR %ptr
937 // on some targets but we don't need to make use of that yet.
938 assert(Matchers
.size() == 1 && "Cannot handle multi-root matchers yet");
940 unsigned LabelID
= Table
.allocateLabelID();
941 Table
<< MatchTable::Opcode("GIM_Try", +1)
942 << MatchTable::Comment("On fail goto")
943 << MatchTable::JumpTarget(LabelID
)
944 << MatchTable::Comment(("Rule ID " + Twine(RuleID
) + " //").str())
945 << MatchTable::LineBreak
;
947 if (!RequiredFeatures
.empty() || HwModeIdx
>= 0) {
948 Table
<< MatchTable::Opcode("GIM_CheckFeatures")
949 << MatchTable::NamedValue(
950 2, getNameForFeatureBitset(RequiredFeatures
, HwModeIdx
))
951 << MatchTable::LineBreak
;
954 if (!RequiredSimplePredicates
.empty()) {
955 for (const auto &Pred
: RequiredSimplePredicates
) {
956 Table
<< MatchTable::Opcode("GIM_CheckSimplePredicate")
957 << MatchTable::NamedValue(2, Pred
) << MatchTable::LineBreak
;
961 Matchers
.front()->emitPredicateOpcodes(Table
, *this);
963 // Check if it's safe to replace registers.
964 for (const auto &MA
: Actions
)
965 MA
->emitAdditionalPredicates(Table
, *this);
967 // We must also check if it's safe to fold the matched instructions.
968 if (InsnVariableIDs
.size() >= 2) {
969 // Invert the map to create stable ordering (by var names)
970 SmallVector
<unsigned, 2> InsnIDs
;
971 for (const auto &Pair
: InsnVariableIDs
) {
972 // Skip the root node since it isn't moving anywhere. Everything else is
973 // sinking to meet it.
974 if (Pair
.first
== Matchers
.front().get())
977 InsnIDs
.push_back(Pair
.second
);
981 for (const auto &InsnID
: InsnIDs
) {
982 // Reject the difficult cases until we have a more accurate check.
983 Table
<< MatchTable::Opcode("GIM_CheckIsSafeToFold")
984 << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
)
985 << MatchTable::LineBreak
;
987 // FIXME: Emit checks to determine it's _actually_ safe to fold and/or
988 // account for unsafe cases.
993 // MI0--> %2 = ... %0
994 // It's not safe to erase MI1. We currently handle this by not
995 // erasing %0 (even when it's dead).
998 // MI1--> %0 = load volatile @a
999 // %1 = load volatile @a
1000 // MI0--> %2 = ... %0
1001 // It's not safe to sink %0's def past %1. We currently handle
1002 // this by rejecting all loads.
1005 // MI1--> %0 = load @a
1007 // MI0--> %2 = ... %0
1008 // It's not safe to sink %0's def past %1. We currently handle
1009 // this by rejecting all loads.
1012 // G_CONDBR %cond, @BB1
1014 // MI1--> %0 = load @a
1017 // MI0--> %2 = ... %0
1018 // It's not always safe to sink %0 across control flow. In this
1019 // case it may introduce a memory fault. We currentl handle
1020 // this by rejecting all loads.
1024 for (const auto &PM
: EpilogueMatchers
)
1025 PM
->emitPredicateOpcodes(Table
, *this);
1027 for (const auto &MA
: Actions
)
1028 MA
->emitActionOpcodes(Table
, *this);
1030 assert((Table
.isWithCoverage() ? !Table
.isCombiner() : true) &&
1031 "Combiner tables don't support coverage!");
1032 if (Table
.isWithCoverage())
1033 Table
<< MatchTable::Opcode("GIR_Coverage")
1034 << MatchTable::IntValue(4, RuleID
) << MatchTable::LineBreak
;
1035 else if (!Table
.isCombiner())
1036 Table
<< MatchTable::Comment(("GIR_Coverage, " + Twine(RuleID
) + ",").str())
1037 << MatchTable::LineBreak
;
1039 Table
<< MatchTable::Opcode("GIR_Done", -1) << MatchTable::LineBreak
1040 << MatchTable::Label(LabelID
);
1041 ++NumPatternEmitted
;
1044 bool RuleMatcher::isHigherPriorityThan(const RuleMatcher
&B
) const {
1045 // Rules involving more match roots have higher priority.
1046 if (Matchers
.size() > B
.Matchers
.size())
1048 if (Matchers
.size() < B
.Matchers
.size())
1051 for (auto Matcher
: zip(Matchers
, B
.Matchers
)) {
1052 if (std::get
<0>(Matcher
)->isHigherPriorityThan(*std::get
<1>(Matcher
)))
1054 if (std::get
<1>(Matcher
)->isHigherPriorityThan(*std::get
<0>(Matcher
)))
1061 unsigned RuleMatcher::countRendererFns() const {
1062 return std::accumulate(
1063 Matchers
.begin(), Matchers
.end(), 0,
1064 [](unsigned A
, const std::unique_ptr
<InstructionMatcher
> &Matcher
) {
1065 return A
+ Matcher
->countRendererFns();
1069 //===- PredicateMatcher ---------------------------------------------------===//
1071 PredicateMatcher::~PredicateMatcher() {}
1073 //===- OperandPredicateMatcher --------------------------------------------===//
1075 OperandPredicateMatcher::~OperandPredicateMatcher() {}
1077 bool OperandPredicateMatcher::isHigherPriorityThan(
1078 const OperandPredicateMatcher
&B
) const {
1079 // Generally speaking, an instruction is more important than an Int or a
1080 // LiteralInt because it can cover more nodes but theres an exception to
1081 // this. G_CONSTANT's are less important than either of those two because they
1082 // are more permissive.
1084 const InstructionOperandMatcher
*AOM
=
1085 dyn_cast
<InstructionOperandMatcher
>(this);
1086 const InstructionOperandMatcher
*BOM
=
1087 dyn_cast
<InstructionOperandMatcher
>(&B
);
1088 bool AIsConstantInsn
= AOM
&& AOM
->getInsnMatcher().isConstantInstruction();
1089 bool BIsConstantInsn
= BOM
&& BOM
->getInsnMatcher().isConstantInstruction();
1092 // The relative priorities between a G_CONSTANT and any other instruction
1093 // don't actually matter but this code is needed to ensure a strict weak
1094 // ordering. This is particularly important on Windows where the rules will
1095 // be incorrectly sorted without it.
1096 if (AIsConstantInsn
!= BIsConstantInsn
)
1097 return AIsConstantInsn
< BIsConstantInsn
;
1101 if (AOM
&& AIsConstantInsn
&& (B
.Kind
== OPM_Int
|| B
.Kind
== OPM_LiteralInt
))
1103 if (BOM
&& BIsConstantInsn
&& (Kind
== OPM_Int
|| Kind
== OPM_LiteralInt
))
1106 return Kind
< B
.Kind
;
1109 //===- SameOperandMatcher -------------------------------------------------===//
1111 void SameOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1112 RuleMatcher
&Rule
) const {
1113 const OperandMatcher
&OtherOM
= Rule
.getOperandMatcher(MatchingName
);
1114 unsigned OtherInsnVarID
= Rule
.getInsnVarID(OtherOM
.getInstructionMatcher());
1115 assert(OtherInsnVarID
== OtherOM
.getInstructionMatcher().getInsnVarID());
1116 const bool IgnoreCopies
= Flags
& GISF_IgnoreCopies
;
1117 Table
<< MatchTable::Opcode(IgnoreCopies
1118 ? "GIM_CheckIsSameOperandIgnoreCopies"
1119 : "GIM_CheckIsSameOperand")
1120 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1121 << MatchTable::Comment("OpIdx") << MatchTable::ULEB128Value(OpIdx
)
1122 << MatchTable::Comment("OtherMI")
1123 << MatchTable::ULEB128Value(OtherInsnVarID
)
1124 << MatchTable::Comment("OtherOpIdx")
1125 << MatchTable::ULEB128Value(OtherOM
.getOpIdx())
1126 << MatchTable::LineBreak
;
1129 //===- LLTOperandMatcher --------------------------------------------------===//
1131 std::map
<LLTCodeGen
, unsigned> LLTOperandMatcher::TypeIDValues
;
1133 MatchTableRecord
LLTOperandMatcher::getValue() const {
1134 const auto VI
= TypeIDValues
.find(Ty
);
1135 if (VI
== TypeIDValues
.end())
1136 return MatchTable::NamedValue(1, getTy().getCxxEnumValue());
1137 return MatchTable::NamedValue(1, getTy().getCxxEnumValue(), VI
->second
);
1140 bool LLTOperandMatcher::hasValue() const {
1141 if (TypeIDValues
.size() != KnownTypes
.size())
1142 initTypeIDValuesMap();
1143 return TypeIDValues
.count(Ty
);
1146 void LLTOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1147 RuleMatcher
&Rule
) const {
1148 Table
<< MatchTable::Opcode("GIM_CheckType") << MatchTable::Comment("MI")
1149 << MatchTable::ULEB128Value(InsnVarID
) << MatchTable::Comment("Op")
1150 << MatchTable::ULEB128Value(OpIdx
) << MatchTable::Comment("Type")
1151 << getValue() << MatchTable::LineBreak
;
1154 //===- PointerToAnyOperandMatcher -----------------------------------------===//
1156 void PointerToAnyOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1157 RuleMatcher
&Rule
) const {
1158 Table
<< MatchTable::Opcode("GIM_CheckPointerToAny")
1159 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1160 << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx
)
1161 << MatchTable::Comment("SizeInBits")
1162 << MatchTable::ULEB128Value(SizeInBits
) << MatchTable::LineBreak
;
1165 //===- RecordNamedOperandMatcher ------------------------------------------===//
1167 void RecordNamedOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1168 RuleMatcher
&Rule
) const {
1169 Table
<< MatchTable::Opcode("GIM_RecordNamedOperand")
1170 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1171 << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx
)
1172 << MatchTable::Comment("StoreIdx") << MatchTable::ULEB128Value(StoreIdx
)
1173 << MatchTable::Comment("Name : " + Name
) << MatchTable::LineBreak
;
1176 //===- RecordRegisterType ------------------------------------------===//
1178 void RecordRegisterType::emitPredicateOpcodes(MatchTable
&Table
,
1179 RuleMatcher
&Rule
) const {
1180 assert(Idx
< 0 && "Temp types always have negative indexes!");
1181 Table
<< MatchTable::Opcode("GIM_RecordRegType") << MatchTable::Comment("MI")
1182 << MatchTable::ULEB128Value(InsnVarID
) << MatchTable::Comment("Op")
1183 << MatchTable::ULEB128Value(OpIdx
) << MatchTable::Comment("TempTypeIdx")
1184 << MatchTable::IntValue(1, Idx
) << MatchTable::LineBreak
;
1187 //===- ComplexPatternOperandMatcher ---------------------------------------===//
1189 void ComplexPatternOperandMatcher::emitPredicateOpcodes(
1190 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1191 unsigned ID
= getAllocatedTemporariesBaseID();
1192 Table
<< MatchTable::Opcode("GIM_CheckComplexPattern")
1193 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1194 << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx
)
1195 << MatchTable::Comment("Renderer") << MatchTable::IntValue(2, ID
)
1196 << MatchTable::NamedValue(2, ("GICP_" + TheDef
.getName()).str())
1197 << MatchTable::LineBreak
;
1200 unsigned ComplexPatternOperandMatcher::getAllocatedTemporariesBaseID() const {
1201 return Operand
.getAllocatedTemporariesBaseID();
1204 //===- RegisterBankOperandMatcher -----------------------------------------===//
1206 bool RegisterBankOperandMatcher::isIdentical(const PredicateMatcher
&B
) const {
1207 return OperandPredicateMatcher::isIdentical(B
) &&
1208 RC
.getDef() == cast
<RegisterBankOperandMatcher
>(&B
)->RC
.getDef();
1211 void RegisterBankOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1212 RuleMatcher
&Rule
) const {
1213 Table
<< MatchTable::Opcode("GIM_CheckRegBankForClass")
1214 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1215 << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx
)
1216 << MatchTable::Comment("RC")
1217 << MatchTable::NamedValue(2, RC
.getQualifiedIdName())
1218 << MatchTable::LineBreak
;
1221 //===- MBBOperandMatcher --------------------------------------------------===//
1223 void MBBOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1224 RuleMatcher
&Rule
) const {
1225 Table
<< MatchTable::Opcode("GIM_CheckIsMBB") << MatchTable::Comment("MI")
1226 << MatchTable::ULEB128Value(InsnVarID
) << MatchTable::Comment("Op")
1227 << MatchTable::ULEB128Value(OpIdx
) << MatchTable::LineBreak
;
1230 //===- ImmOperandMatcher --------------------------------------------------===//
1232 void ImmOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1233 RuleMatcher
&Rule
) const {
1234 Table
<< MatchTable::Opcode("GIM_CheckIsImm") << MatchTable::Comment("MI")
1235 << MatchTable::ULEB128Value(InsnVarID
) << MatchTable::Comment("Op")
1236 << MatchTable::ULEB128Value(OpIdx
) << MatchTable::LineBreak
;
1239 //===- ConstantIntOperandMatcher ------------------------------------------===//
1241 void ConstantIntOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1242 RuleMatcher
&Rule
) const {
1243 const bool IsInt8
= isInt
<8>(Value
);
1244 Table
<< MatchTable::Opcode(IsInt8
? "GIM_CheckConstantInt8"
1245 : "GIM_CheckConstantInt")
1246 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1247 << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx
)
1248 << MatchTable::IntValue(IsInt8
? 1 : 8, Value
) << MatchTable::LineBreak
;
1251 //===- LiteralIntOperandMatcher -------------------------------------------===//
1253 void LiteralIntOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1254 RuleMatcher
&Rule
) const {
1255 Table
<< MatchTable::Opcode("GIM_CheckLiteralInt")
1256 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1257 << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx
)
1258 << MatchTable::IntValue(8, Value
) << MatchTable::LineBreak
;
1261 //===- CmpPredicateOperandMatcher -----------------------------------------===//
1263 void CmpPredicateOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1264 RuleMatcher
&Rule
) const {
1265 Table
<< MatchTable::Opcode("GIM_CheckCmpPredicate")
1266 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1267 << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx
)
1268 << MatchTable::Comment("Predicate")
1269 << MatchTable::NamedValue(2, "CmpInst", PredName
)
1270 << MatchTable::LineBreak
;
1273 //===- IntrinsicIDOperandMatcher ------------------------------------------===//
1275 void IntrinsicIDOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1276 RuleMatcher
&Rule
) const {
1277 Table
<< MatchTable::Opcode("GIM_CheckIntrinsicID")
1278 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1279 << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx
)
1280 << MatchTable::NamedValue(2, "Intrinsic::" + II
->EnumName
)
1281 << MatchTable::LineBreak
;
1284 //===- OperandImmPredicateMatcher -----------------------------------------===//
1286 void OperandImmPredicateMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1287 RuleMatcher
&Rule
) const {
1288 Table
<< MatchTable::Opcode("GIM_CheckImmOperandPredicate")
1289 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1290 << MatchTable::Comment("MO") << MatchTable::ULEB128Value(OpIdx
)
1291 << MatchTable::Comment("Predicate")
1292 << MatchTable::NamedValue(2, getEnumNameForPredicate(Predicate
))
1293 << MatchTable::LineBreak
;
1296 //===- OperandMatcher -----------------------------------------------------===//
1298 std::string
OperandMatcher::getOperandExpr(unsigned InsnVarID
) const {
1299 return "State.MIs[" + llvm::to_string(InsnVarID
) + "]->getOperand(" +
1300 llvm::to_string(OpIdx
) + ")";
1303 unsigned OperandMatcher::getInsnVarID() const { return Insn
.getInsnVarID(); }
1305 TempTypeIdx
OperandMatcher::getTempTypeIdx(RuleMatcher
&Rule
) {
1307 // Temp type index not assigned yet, so assign one and add the necessary
1309 TTIdx
= Rule
.getNextTempTypeIdx();
1311 addPredicate
<RecordRegisterType
>(TTIdx
);
1317 void OperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1318 RuleMatcher
&Rule
) {
1320 std::string Comment
;
1321 raw_string_ostream
CommentOS(Comment
);
1322 CommentOS
<< "MIs[" << getInsnVarID() << "] ";
1323 if (SymbolicName
.empty())
1324 CommentOS
<< "Operand " << OpIdx
;
1326 CommentOS
<< SymbolicName
;
1327 Table
<< MatchTable::Comment(Comment
) << MatchTable::LineBreak
;
1330 emitPredicateListOpcodes(Table
, Rule
);
1333 bool OperandMatcher::isHigherPriorityThan(OperandMatcher
&B
) {
1334 // Operand matchers involving more predicates have higher priority.
1335 if (predicates_size() > B
.predicates_size())
1337 if (predicates_size() < B
.predicates_size())
1340 // This assumes that predicates are added in a consistent order.
1341 for (auto &&Predicate
: zip(predicates(), B
.predicates())) {
1342 if (std::get
<0>(Predicate
)->isHigherPriorityThan(*std::get
<1>(Predicate
)))
1344 if (std::get
<1>(Predicate
)->isHigherPriorityThan(*std::get
<0>(Predicate
)))
1351 unsigned OperandMatcher::countRendererFns() {
1352 return std::accumulate(
1353 predicates().begin(), predicates().end(), 0,
1355 const std::unique_ptr
<OperandPredicateMatcher
> &Predicate
) {
1356 return A
+ Predicate
->countRendererFns();
1360 Error
OperandMatcher::addTypeCheckPredicate(const TypeSetByHwMode
&VTy
,
1361 bool OperandIsAPointer
) {
1362 if (!VTy
.isMachineValueType())
1363 return failUnsupported("unsupported typeset");
1365 if (VTy
.getMachineValueType() == MVT::iPTR
&& OperandIsAPointer
) {
1366 addPredicate
<PointerToAnyOperandMatcher
>(0);
1367 return Error::success();
1370 auto OpTyOrNone
= MVTToLLT(VTy
.getMachineValueType().SimpleTy
);
1372 return failUnsupported("unsupported type");
1374 if (OperandIsAPointer
)
1375 addPredicate
<PointerToAnyOperandMatcher
>(OpTyOrNone
->get().getSizeInBits());
1376 else if (VTy
.isPointer())
1377 addPredicate
<LLTOperandMatcher
>(
1378 LLT::pointer(VTy
.getPtrAddrSpace(), OpTyOrNone
->get().getSizeInBits()));
1380 addPredicate
<LLTOperandMatcher
>(*OpTyOrNone
);
1381 return Error::success();
1384 //===- InstructionOpcodeMatcher -------------------------------------------===//
1386 DenseMap
<const CodeGenInstruction
*, unsigned>
1387 InstructionOpcodeMatcher::OpcodeValues
;
1390 InstructionOpcodeMatcher::getInstValue(const CodeGenInstruction
*I
) const {
1391 const auto VI
= OpcodeValues
.find(I
);
1392 if (VI
!= OpcodeValues
.end())
1393 return MatchTable::NamedValue(2, I
->Namespace
, I
->TheDef
->getName(),
1395 return MatchTable::NamedValue(2, I
->Namespace
, I
->TheDef
->getName());
1398 void InstructionOpcodeMatcher::initOpcodeValuesMap(
1399 const CodeGenTarget
&Target
) {
1400 OpcodeValues
.clear();
1402 unsigned OpcodeValue
= 0;
1403 for (const CodeGenInstruction
*I
: Target
.getInstructionsByEnumValue())
1404 OpcodeValues
[I
] = OpcodeValue
++;
1407 MatchTableRecord
InstructionOpcodeMatcher::getValue() const {
1408 assert(Insts
.size() == 1);
1410 const CodeGenInstruction
*I
= Insts
[0];
1411 const auto VI
= OpcodeValues
.find(I
);
1412 if (VI
!= OpcodeValues
.end())
1413 return MatchTable::NamedValue(2, I
->Namespace
, I
->TheDef
->getName(),
1415 return MatchTable::NamedValue(2, I
->Namespace
, I
->TheDef
->getName());
1418 void InstructionOpcodeMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1419 RuleMatcher
&Rule
) const {
1420 StringRef CheckType
=
1421 Insts
.size() == 1 ? "GIM_CheckOpcode" : "GIM_CheckOpcodeIsEither";
1422 Table
<< MatchTable::Opcode(CheckType
) << MatchTable::Comment("MI")
1423 << MatchTable::ULEB128Value(InsnVarID
);
1425 for (const CodeGenInstruction
*I
: Insts
)
1426 Table
<< getInstValue(I
);
1427 Table
<< MatchTable::LineBreak
;
1430 bool InstructionOpcodeMatcher::isHigherPriorityThan(
1431 const InstructionPredicateMatcher
&B
) const {
1432 if (InstructionPredicateMatcher::isHigherPriorityThan(B
))
1434 if (B
.InstructionPredicateMatcher::isHigherPriorityThan(*this))
1437 // Prioritize opcodes for cosmetic reasons in the generated source. Although
1438 // this is cosmetic at the moment, we may want to drive a similar ordering
1439 // using instruction frequency information to improve compile time.
1440 if (const InstructionOpcodeMatcher
*BO
=
1441 dyn_cast
<InstructionOpcodeMatcher
>(&B
))
1442 return Insts
[0]->TheDef
->getName() < BO
->Insts
[0]->TheDef
->getName();
1447 bool InstructionOpcodeMatcher::isConstantInstruction() const {
1448 return Insts
.size() == 1 && Insts
[0]->TheDef
->getName() == "G_CONSTANT";
1451 StringRef
InstructionOpcodeMatcher::getOpcode() const {
1452 return Insts
[0]->TheDef
->getName();
1455 bool InstructionOpcodeMatcher::isVariadicNumOperands() const {
1456 // If one is variadic, they all should be.
1457 return Insts
[0]->Operands
.isVariadic
;
1460 StringRef
InstructionOpcodeMatcher::getOperandType(unsigned OpIdx
) const {
1461 // Types expected to be uniform for all alternatives.
1462 return Insts
[0]->Operands
[OpIdx
].OperandType
;
1465 //===- InstructionNumOperandsMatcher --------------------------------------===//
1467 void InstructionNumOperandsMatcher::emitPredicateOpcodes(
1468 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1469 Table
<< MatchTable::Opcode("GIM_CheckNumOperands")
1470 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1471 << MatchTable::Comment("Expected")
1472 << MatchTable::ULEB128Value(NumOperands
) << MatchTable::LineBreak
;
1475 //===- InstructionImmPredicateMatcher -------------------------------------===//
1477 bool InstructionImmPredicateMatcher::isIdentical(
1478 const PredicateMatcher
&B
) const {
1479 return InstructionPredicateMatcher::isIdentical(B
) &&
1480 Predicate
.getOrigPatFragRecord() ==
1481 cast
<InstructionImmPredicateMatcher
>(&B
)
1482 ->Predicate
.getOrigPatFragRecord();
1485 void InstructionImmPredicateMatcher::emitPredicateOpcodes(
1486 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1487 Table
<< MatchTable::Opcode(getMatchOpcodeForImmPredicate(Predicate
))
1488 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1489 << MatchTable::Comment("Predicate")
1490 << MatchTable::NamedValue(2, getEnumNameForPredicate(Predicate
))
1491 << MatchTable::LineBreak
;
1494 //===- AtomicOrderingMMOPredicateMatcher ----------------------------------===//
1496 bool AtomicOrderingMMOPredicateMatcher::isIdentical(
1497 const PredicateMatcher
&B
) const {
1498 if (!InstructionPredicateMatcher::isIdentical(B
))
1500 const auto &R
= *cast
<AtomicOrderingMMOPredicateMatcher
>(&B
);
1501 return Order
== R
.Order
&& Comparator
== R
.Comparator
;
1504 void AtomicOrderingMMOPredicateMatcher::emitPredicateOpcodes(
1505 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1506 StringRef Opcode
= "GIM_CheckAtomicOrdering";
1508 if (Comparator
== AO_OrStronger
)
1509 Opcode
= "GIM_CheckAtomicOrderingOrStrongerThan";
1510 if (Comparator
== AO_WeakerThan
)
1511 Opcode
= "GIM_CheckAtomicOrderingWeakerThan";
1513 Table
<< MatchTable::Opcode(Opcode
) << MatchTable::Comment("MI")
1514 << MatchTable::ULEB128Value(InsnVarID
) << MatchTable::Comment("Order")
1515 << MatchTable::NamedValue(1,
1516 ("(uint8_t)AtomicOrdering::" + Order
).str())
1517 << MatchTable::LineBreak
;
1520 //===- MemorySizePredicateMatcher -----------------------------------------===//
1522 void MemorySizePredicateMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1523 RuleMatcher
&Rule
) const {
1524 Table
<< MatchTable::Opcode("GIM_CheckMemorySizeEqualTo")
1525 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1526 << MatchTable::Comment("MMO") << MatchTable::ULEB128Value(MMOIdx
)
1527 << MatchTable::Comment("Size") << MatchTable::IntValue(4, Size
)
1528 << MatchTable::LineBreak
;
1531 //===- MemoryAddressSpacePredicateMatcher ---------------------------------===//
1533 bool MemoryAddressSpacePredicateMatcher::isIdentical(
1534 const PredicateMatcher
&B
) const {
1535 if (!InstructionPredicateMatcher::isIdentical(B
))
1537 auto *Other
= cast
<MemoryAddressSpacePredicateMatcher
>(&B
);
1538 return MMOIdx
== Other
->MMOIdx
&& AddrSpaces
== Other
->AddrSpaces
;
1541 void MemoryAddressSpacePredicateMatcher::emitPredicateOpcodes(
1542 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1543 Table
<< MatchTable::Opcode("GIM_CheckMemoryAddressSpace")
1544 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1545 << MatchTable::Comment("MMO")
1546 << MatchTable::ULEB128Value(MMOIdx
)
1547 // Encode number of address spaces to expect.
1548 << MatchTable::Comment("NumAddrSpace")
1549 << MatchTable::ULEB128Value(AddrSpaces
.size());
1550 for (unsigned AS
: AddrSpaces
)
1551 Table
<< MatchTable::Comment("AddrSpace") << MatchTable::ULEB128Value(AS
);
1553 Table
<< MatchTable::LineBreak
;
1556 //===- MemoryAlignmentPredicateMatcher ------------------------------------===//
1558 bool MemoryAlignmentPredicateMatcher::isIdentical(
1559 const PredicateMatcher
&B
) const {
1560 if (!InstructionPredicateMatcher::isIdentical(B
))
1562 auto *Other
= cast
<MemoryAlignmentPredicateMatcher
>(&B
);
1563 return MMOIdx
== Other
->MMOIdx
&& MinAlign
== Other
->MinAlign
;
1566 void MemoryAlignmentPredicateMatcher::emitPredicateOpcodes(
1567 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1568 Table
<< MatchTable::Opcode("GIM_CheckMemoryAlignment")
1569 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1570 << MatchTable::Comment("MMO") << MatchTable::ULEB128Value(MMOIdx
)
1571 << MatchTable::Comment("MinAlign") << MatchTable::ULEB128Value(MinAlign
)
1572 << MatchTable::LineBreak
;
1575 //===- MemoryVsLLTSizePredicateMatcher ------------------------------------===//
1577 bool MemoryVsLLTSizePredicateMatcher::isIdentical(
1578 const PredicateMatcher
&B
) const {
1579 return InstructionPredicateMatcher::isIdentical(B
) &&
1580 MMOIdx
== cast
<MemoryVsLLTSizePredicateMatcher
>(&B
)->MMOIdx
&&
1581 Relation
== cast
<MemoryVsLLTSizePredicateMatcher
>(&B
)->Relation
&&
1582 OpIdx
== cast
<MemoryVsLLTSizePredicateMatcher
>(&B
)->OpIdx
;
1585 void MemoryVsLLTSizePredicateMatcher::emitPredicateOpcodes(
1586 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1587 Table
<< MatchTable::Opcode(
1588 Relation
== EqualTo
? "GIM_CheckMemorySizeEqualToLLT"
1589 : Relation
== GreaterThan
? "GIM_CheckMemorySizeGreaterThanLLT"
1590 : "GIM_CheckMemorySizeLessThanLLT")
1591 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1592 << MatchTable::Comment("MMO") << MatchTable::ULEB128Value(MMOIdx
)
1593 << MatchTable::Comment("OpIdx") << MatchTable::ULEB128Value(OpIdx
)
1594 << MatchTable::LineBreak
;
1597 //===- VectorSplatImmPredicateMatcher -------------------------------------===//
1599 void VectorSplatImmPredicateMatcher::emitPredicateOpcodes(
1600 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1601 if (Kind
== AllOnes
)
1602 Table
<< MatchTable::Opcode("GIM_CheckIsBuildVectorAllOnes");
1604 Table
<< MatchTable::Opcode("GIM_CheckIsBuildVectorAllZeros");
1606 Table
<< MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
);
1607 Table
<< MatchTable::LineBreak
;
1610 //===- GenericInstructionPredicateMatcher ---------------------------------===//
1612 GenericInstructionPredicateMatcher::GenericInstructionPredicateMatcher(
1613 unsigned InsnVarID
, TreePredicateFn Predicate
)
1614 : GenericInstructionPredicateMatcher(InsnVarID
,
1615 getEnumNameForPredicate(Predicate
)) {}
1617 bool GenericInstructionPredicateMatcher::isIdentical(
1618 const PredicateMatcher
&B
) const {
1619 return InstructionPredicateMatcher::isIdentical(B
) &&
1621 static_cast<const GenericInstructionPredicateMatcher
&>(B
).EnumVal
;
1623 void GenericInstructionPredicateMatcher::emitPredicateOpcodes(
1624 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1625 Table
<< MatchTable::Opcode("GIM_CheckCxxInsnPredicate")
1626 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1627 << MatchTable::Comment("FnId") << MatchTable::NamedValue(2, EnumVal
)
1628 << MatchTable::LineBreak
;
1631 //===- MIFlagsInstructionPredicateMatcher ---------------------------------===//
1633 bool MIFlagsInstructionPredicateMatcher::isIdentical(
1634 const PredicateMatcher
&B
) const {
1635 if (!InstructionPredicateMatcher::isIdentical(B
))
1638 static_cast<const MIFlagsInstructionPredicateMatcher
&>(B
);
1639 return Flags
== Other
.Flags
&& CheckNot
== Other
.CheckNot
;
1642 void MIFlagsInstructionPredicateMatcher::emitPredicateOpcodes(
1643 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1644 Table
<< MatchTable::Opcode(CheckNot
? "GIM_MIFlagsNot" : "GIM_MIFlags")
1645 << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID
)
1646 << MatchTable::NamedValue(4, join(Flags
, " | "))
1647 << MatchTable::LineBreak
;
1650 //===- InstructionMatcher -------------------------------------------------===//
1653 InstructionMatcher::addOperand(unsigned OpIdx
, const std::string
&SymbolicName
,
1654 unsigned AllocatedTemporariesBaseID
) {
1655 Operands
.emplace_back(new OperandMatcher(*this, OpIdx
, SymbolicName
,
1656 AllocatedTemporariesBaseID
));
1657 if (!SymbolicName
.empty())
1658 Rule
.defineOperand(SymbolicName
, *Operands
.back());
1660 return *Operands
.back();
1663 OperandMatcher
&InstructionMatcher::getOperand(unsigned OpIdx
) {
1664 auto I
= llvm::find_if(Operands
,
1665 [&OpIdx
](const std::unique_ptr
<OperandMatcher
> &X
) {
1666 return X
->getOpIdx() == OpIdx
;
1668 if (I
!= Operands
.end())
1670 llvm_unreachable("Failed to lookup operand");
1673 OperandMatcher
&InstructionMatcher::addPhysRegInput(Record
*Reg
, unsigned OpIdx
,
1674 unsigned TempOpIdx
) {
1675 assert(SymbolicName
.empty());
1676 OperandMatcher
*OM
= new OperandMatcher(*this, OpIdx
, "", TempOpIdx
);
1677 Operands
.emplace_back(OM
);
1678 Rule
.definePhysRegOperand(Reg
, *OM
);
1679 PhysRegInputs
.emplace_back(Reg
, OpIdx
);
1683 void InstructionMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1684 RuleMatcher
&Rule
) {
1685 if (NumOperandsCheck
)
1686 InstructionNumOperandsMatcher(InsnVarID
, getNumOperands())
1687 .emitPredicateOpcodes(Table
, Rule
);
1689 // First emit all instruction level predicates need to be verified before we
1690 // can verify operands.
1691 emitFilteredPredicateListOpcodes(
1692 [](const PredicateMatcher
&P
) { return !P
.dependsOnOperands(); }, Table
,
1695 // Emit all operand constraints.
1696 for (const auto &Operand
: Operands
)
1697 Operand
->emitPredicateOpcodes(Table
, Rule
);
1699 // All of the tablegen defined predicates should now be matched. Now emit
1700 // any custom predicates that rely on all generated checks.
1701 emitFilteredPredicateListOpcodes(
1702 [](const PredicateMatcher
&P
) { return P
.dependsOnOperands(); }, Table
,
1706 bool InstructionMatcher::isHigherPriorityThan(InstructionMatcher
&B
) {
1707 // Instruction matchers involving more operands have higher priority.
1708 if (Operands
.size() > B
.Operands
.size())
1710 if (Operands
.size() < B
.Operands
.size())
1713 for (auto &&P
: zip(predicates(), B
.predicates())) {
1714 auto L
= static_cast<InstructionPredicateMatcher
*>(std::get
<0>(P
).get());
1715 auto R
= static_cast<InstructionPredicateMatcher
*>(std::get
<1>(P
).get());
1716 if (L
->isHigherPriorityThan(*R
))
1718 if (R
->isHigherPriorityThan(*L
))
1722 for (auto Operand
: zip(Operands
, B
.Operands
)) {
1723 if (std::get
<0>(Operand
)->isHigherPriorityThan(*std::get
<1>(Operand
)))
1725 if (std::get
<1>(Operand
)->isHigherPriorityThan(*std::get
<0>(Operand
)))
1732 unsigned InstructionMatcher::countRendererFns() {
1733 return std::accumulate(
1734 predicates().begin(), predicates().end(), 0,
1736 const std::unique_ptr
<PredicateMatcher
> &Predicate
) {
1737 return A
+ Predicate
->countRendererFns();
1740 Operands
.begin(), Operands
.end(), 0,
1741 [](unsigned A
, const std::unique_ptr
<OperandMatcher
> &Operand
) {
1742 return A
+ Operand
->countRendererFns();
1746 void InstructionMatcher::optimize() {
1747 SmallVector
<std::unique_ptr
<PredicateMatcher
>, 8> Stash
;
1748 const auto &OpcMatcher
= getOpcodeMatcher();
1750 Stash
.push_back(predicates_pop_front());
1751 if (Stash
.back().get() == &OpcMatcher
) {
1752 if (NumOperandsCheck
&& OpcMatcher
.isVariadicNumOperands() &&
1753 getNumOperands() != 0)
1755 new InstructionNumOperandsMatcher(InsnVarID
, getNumOperands()));
1756 NumOperandsCheck
= false;
1758 for (auto &OM
: Operands
)
1759 for (auto &OP
: OM
->predicates())
1760 if (isa
<IntrinsicIDOperandMatcher
>(OP
)) {
1761 Stash
.push_back(std::move(OP
));
1762 OM
->eraseNullPredicates();
1767 if (InsnVarID
> 0) {
1768 assert(!Operands
.empty() && "Nested instruction is expected to def a vreg");
1769 for (auto &OP
: Operands
[0]->predicates())
1771 Operands
[0]->eraseNullPredicates();
1773 for (auto &OM
: Operands
) {
1774 for (auto &OP
: OM
->predicates())
1775 if (isa
<LLTOperandMatcher
>(OP
))
1776 Stash
.push_back(std::move(OP
));
1777 OM
->eraseNullPredicates();
1779 while (!Stash
.empty())
1780 prependPredicate(Stash
.pop_back_val());
1783 //===- InstructionOperandMatcher ------------------------------------------===//
1785 void InstructionOperandMatcher::emitCaptureOpcodes(MatchTable
&Table
,
1786 RuleMatcher
&Rule
) const {
1787 const unsigned NewInsnVarID
= InsnMatcher
->getInsnVarID();
1788 const bool IgnoreCopies
= Flags
& GISF_IgnoreCopies
;
1789 Table
<< MatchTable::Opcode(IgnoreCopies
? "GIM_RecordInsnIgnoreCopies"
1791 << MatchTable::Comment("DefineMI")
1792 << MatchTable::ULEB128Value(NewInsnVarID
) << MatchTable::Comment("MI")
1793 << MatchTable::ULEB128Value(getInsnVarID())
1794 << MatchTable::Comment("OpIdx") << MatchTable::ULEB128Value(getOpIdx())
1795 << MatchTable::Comment("MIs[" + llvm::to_string(NewInsnVarID
) + "]")
1796 << MatchTable::LineBreak
;
1799 bool InstructionOperandMatcher::isHigherPriorityThan(
1800 const OperandPredicateMatcher
&B
) const {
1801 if (OperandPredicateMatcher::isHigherPriorityThan(B
))
1803 if (B
.OperandPredicateMatcher::isHigherPriorityThan(*this))
1806 if (const InstructionOperandMatcher
*BP
=
1807 dyn_cast
<InstructionOperandMatcher
>(&B
))
1808 if (InsnMatcher
->isHigherPriorityThan(*BP
->InsnMatcher
))
1813 //===- OperandRenderer ----------------------------------------------------===//
1815 OperandRenderer::~OperandRenderer() {}
1817 //===- CopyRenderer -------------------------------------------------------===//
1819 void CopyRenderer::emitRenderOpcodes(MatchTable
&Table
,
1820 RuleMatcher
&Rule
) const {
1821 const OperandMatcher
&Operand
= Rule
.getOperandMatcher(SymbolicName
);
1822 unsigned OldInsnVarID
= Rule
.getInsnVarID(Operand
.getInstructionMatcher());
1823 Table
<< MatchTable::Opcode("GIR_Copy") << MatchTable::Comment("NewInsnID")
1824 << MatchTable::ULEB128Value(NewInsnID
)
1825 << MatchTable::Comment("OldInsnID")
1826 << MatchTable::ULEB128Value(OldInsnVarID
)
1827 << MatchTable::Comment("OpIdx")
1828 << MatchTable::ULEB128Value(Operand
.getOpIdx())
1829 << MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
1832 //===- CopyPhysRegRenderer ------------------------------------------------===//
1834 void CopyPhysRegRenderer::emitRenderOpcodes(MatchTable
&Table
,
1835 RuleMatcher
&Rule
) const {
1836 const OperandMatcher
&Operand
= Rule
.getPhysRegOperandMatcher(PhysReg
);
1837 unsigned OldInsnVarID
= Rule
.getInsnVarID(Operand
.getInstructionMatcher());
1838 Table
<< MatchTable::Opcode("GIR_Copy") << MatchTable::Comment("NewInsnID")
1839 << MatchTable::ULEB128Value(NewInsnID
)
1840 << MatchTable::Comment("OldInsnID")
1841 << MatchTable::ULEB128Value(OldInsnVarID
)
1842 << MatchTable::Comment("OpIdx")
1843 << MatchTable::ULEB128Value(Operand
.getOpIdx())
1844 << MatchTable::Comment(PhysReg
->getName()) << MatchTable::LineBreak
;
1847 //===- CopyOrAddZeroRegRenderer -------------------------------------------===//
1849 void CopyOrAddZeroRegRenderer::emitRenderOpcodes(MatchTable
&Table
,
1850 RuleMatcher
&Rule
) const {
1851 const OperandMatcher
&Operand
= Rule
.getOperandMatcher(SymbolicName
);
1852 unsigned OldInsnVarID
= Rule
.getInsnVarID(Operand
.getInstructionMatcher());
1853 Table
<< MatchTable::Opcode("GIR_CopyOrAddZeroReg")
1854 << MatchTable::Comment("NewInsnID")
1855 << MatchTable::ULEB128Value(NewInsnID
)
1856 << MatchTable::Comment("OldInsnID")
1857 << MatchTable::ULEB128Value(OldInsnVarID
)
1858 << MatchTable::Comment("OpIdx")
1859 << MatchTable::ULEB128Value(Operand
.getOpIdx())
1860 << MatchTable::NamedValue(
1862 (ZeroRegisterDef
->getValue("Namespace")
1863 ? ZeroRegisterDef
->getValueAsString("Namespace")
1865 ZeroRegisterDef
->getName())
1866 << MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
1869 //===- CopyConstantAsImmRenderer ------------------------------------------===//
1871 void CopyConstantAsImmRenderer::emitRenderOpcodes(MatchTable
&Table
,
1872 RuleMatcher
&Rule
) const {
1873 InstructionMatcher
&InsnMatcher
= Rule
.getInstructionMatcher(SymbolicName
);
1874 unsigned OldInsnVarID
= Rule
.getInsnVarID(InsnMatcher
);
1875 Table
<< MatchTable::Opcode(Signed
? "GIR_CopyConstantAsSImm"
1876 : "GIR_CopyConstantAsUImm")
1877 << MatchTable::Comment("NewInsnID")
1878 << MatchTable::ULEB128Value(NewInsnID
)
1879 << MatchTable::Comment("OldInsnID")
1880 << MatchTable::ULEB128Value(OldInsnVarID
)
1881 << MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
1884 //===- CopyFConstantAsFPImmRenderer ---------------------------------------===//
1886 void CopyFConstantAsFPImmRenderer::emitRenderOpcodes(MatchTable
&Table
,
1887 RuleMatcher
&Rule
) const {
1888 InstructionMatcher
&InsnMatcher
= Rule
.getInstructionMatcher(SymbolicName
);
1889 unsigned OldInsnVarID
= Rule
.getInsnVarID(InsnMatcher
);
1890 Table
<< MatchTable::Opcode("GIR_CopyFConstantAsFPImm")
1891 << MatchTable::Comment("NewInsnID")
1892 << MatchTable::ULEB128Value(NewInsnID
)
1893 << MatchTable::Comment("OldInsnID")
1894 << MatchTable::ULEB128Value(OldInsnVarID
)
1895 << MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
1898 //===- CopySubRegRenderer -------------------------------------------------===//
1900 void CopySubRegRenderer::emitRenderOpcodes(MatchTable
&Table
,
1901 RuleMatcher
&Rule
) const {
1902 const OperandMatcher
&Operand
= Rule
.getOperandMatcher(SymbolicName
);
1903 unsigned OldInsnVarID
= Rule
.getInsnVarID(Operand
.getInstructionMatcher());
1904 Table
<< MatchTable::Opcode("GIR_CopySubReg")
1905 << MatchTable::Comment("NewInsnID")
1906 << MatchTable::ULEB128Value(NewInsnID
)
1907 << MatchTable::Comment("OldInsnID")
1908 << MatchTable::ULEB128Value(OldInsnVarID
)
1909 << MatchTable::Comment("OpIdx")
1910 << MatchTable::ULEB128Value(Operand
.getOpIdx())
1911 << MatchTable::Comment("SubRegIdx")
1912 << MatchTable::IntValue(2, SubReg
->EnumValue
)
1913 << MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
1916 //===- AddRegisterRenderer ------------------------------------------------===//
1918 void AddRegisterRenderer::emitRenderOpcodes(MatchTable
&Table
,
1919 RuleMatcher
&Rule
) const {
1920 Table
<< MatchTable::Opcode("GIR_AddRegister")
1921 << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
);
1922 if (RegisterDef
->getName() != "zero_reg") {
1923 Table
<< MatchTable::NamedValue(
1925 (RegisterDef
->getValue("Namespace")
1926 ? RegisterDef
->getValueAsString("Namespace")
1928 RegisterDef
->getName());
1930 Table
<< MatchTable::NamedValue(2, Target
.getRegNamespace(), "NoRegister");
1932 Table
<< MatchTable::Comment("AddRegisterRegFlags");
1934 // TODO: This is encoded as a 64-bit element, but only 16 or 32-bits are
1935 // really needed for a physical register reference. We can pack the
1936 // register and flags in a single field.
1938 Table
<< MatchTable::NamedValue(2, "RegState::Define");
1940 Table
<< MatchTable::IntValue(2, 0);
1941 Table
<< MatchTable::LineBreak
;
1944 //===- TempRegRenderer ----------------------------------------------------===//
1946 void TempRegRenderer::emitRenderOpcodes(MatchTable
&Table
,
1947 RuleMatcher
&Rule
) const {
1948 const bool NeedsFlags
= (SubRegIdx
|| IsDef
);
1951 Table
<< MatchTable::Opcode("GIR_AddTempSubRegister");
1953 Table
<< MatchTable::Opcode(NeedsFlags
? "GIR_AddTempRegister"
1954 : "GIR_AddSimpleTempRegister");
1956 Table
<< MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
)
1957 << MatchTable::Comment("TempRegID")
1958 << MatchTable::ULEB128Value(TempRegID
);
1961 Table
<< MatchTable::LineBreak
;
1965 Table
<< MatchTable::Comment("TempRegFlags");
1967 SmallString
<32> RegFlags
;
1968 RegFlags
+= "RegState::Define";
1970 RegFlags
+= "|RegState::Dead";
1971 Table
<< MatchTable::NamedValue(2, RegFlags
);
1973 Table
<< MatchTable::IntValue(2, 0);
1976 Table
<< MatchTable::NamedValue(2, SubRegIdx
->getQualifiedName());
1977 Table
<< MatchTable::LineBreak
;
1980 //===- ImmRenderer --------------------------------------------------------===//
1982 void ImmRenderer::emitAddImm(MatchTable
&Table
, RuleMatcher
&RM
,
1983 unsigned InsnID
, int64_t Imm
, StringRef ImmName
) {
1984 const bool IsInt8
= isInt
<8>(Imm
);
1986 Table
<< MatchTable::Opcode(IsInt8
? "GIR_AddImm8" : "GIR_AddImm")
1987 << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
)
1988 << MatchTable::Comment(ImmName
)
1989 << MatchTable::IntValue(IsInt8
? 1 : 8, Imm
) << MatchTable::LineBreak
;
1992 void ImmRenderer::emitRenderOpcodes(MatchTable
&Table
,
1993 RuleMatcher
&Rule
) const {
1995 assert(Table
.isCombiner() &&
1996 "ConstantInt immediate are only for combiners!");
1997 Table
<< MatchTable::Opcode("GIR_AddCImm") << MatchTable::Comment("InsnID")
1998 << MatchTable::ULEB128Value(InsnID
) << MatchTable::Comment("Type")
1999 << *CImmLLT
<< MatchTable::Comment("Imm")
2000 << MatchTable::IntValue(8, Imm
) << MatchTable::LineBreak
;
2002 emitAddImm(Table
, Rule
, InsnID
, Imm
);
2005 //===- SubRegIndexRenderer ------------------------------------------------===//
2007 void SubRegIndexRenderer::emitRenderOpcodes(MatchTable
&Table
,
2008 RuleMatcher
&Rule
) const {
2009 ImmRenderer::emitAddImm(Table
, Rule
, InsnID
, SubRegIdx
->EnumValue
,
2013 //===- RenderComplexPatternOperand ----------------------------------------===//
2015 void RenderComplexPatternOperand::emitRenderOpcodes(MatchTable
&Table
,
2016 RuleMatcher
&Rule
) const {
2017 Table
<< MatchTable::Opcode(
2018 SubOperand
? (SubReg
? "GIR_ComplexSubOperandSubRegRenderer"
2019 : "GIR_ComplexSubOperandRenderer")
2020 : "GIR_ComplexRenderer")
2021 << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
)
2022 << MatchTable::Comment("RendererID")
2023 << MatchTable::IntValue(2, RendererID
);
2025 Table
<< MatchTable::Comment("SubOperand")
2026 << MatchTable::ULEB128Value(*SubOperand
);
2028 Table
<< MatchTable::Comment("SubRegIdx")
2029 << MatchTable::IntValue(2, SubReg
->EnumValue
);
2030 Table
<< MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
2033 //===- CustomRenderer -----------------------------------------------------===//
2035 void CustomRenderer::emitRenderOpcodes(MatchTable
&Table
,
2036 RuleMatcher
&Rule
) const {
2037 InstructionMatcher
&InsnMatcher
= Rule
.getInstructionMatcher(SymbolicName
);
2038 unsigned OldInsnVarID
= Rule
.getInsnVarID(InsnMatcher
);
2039 Table
<< MatchTable::Opcode("GIR_CustomRenderer")
2040 << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
)
2041 << MatchTable::Comment("OldInsnID")
2042 << MatchTable::ULEB128Value(OldInsnVarID
)
2043 << MatchTable::Comment("Renderer")
2044 << MatchTable::NamedValue(
2045 2, "GICR_" + Renderer
.getValueAsString("RendererFn").str())
2046 << MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
2049 //===- CustomOperandRenderer ----------------------------------------------===//
2051 void CustomOperandRenderer::emitRenderOpcodes(MatchTable
&Table
,
2052 RuleMatcher
&Rule
) const {
2053 const OperandMatcher
&OpdMatcher
= Rule
.getOperandMatcher(SymbolicName
);
2054 Table
<< MatchTable::Opcode("GIR_CustomOperandRenderer")
2055 << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
)
2056 << MatchTable::Comment("OldInsnID")
2057 << MatchTable::ULEB128Value(OpdMatcher
.getInsnVarID())
2058 << MatchTable::Comment("OpIdx")
2059 << MatchTable::ULEB128Value(OpdMatcher
.getOpIdx())
2060 << MatchTable::Comment("OperandRenderer")
2061 << MatchTable::NamedValue(
2062 2, "GICR_" + Renderer
.getValueAsString("RendererFn").str())
2063 << MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
2066 //===- CustomCXXAction ----------------------------------------------------===//
2068 void CustomCXXAction::emitActionOpcodes(MatchTable
&Table
,
2069 RuleMatcher
&Rule
) const {
2070 Table
<< MatchTable::Opcode("GIR_CustomAction")
2071 << MatchTable::NamedValue(2, FnEnumName
) << MatchTable::LineBreak
;
2074 //===- BuildMIAction ------------------------------------------------------===//
2076 bool BuildMIAction::canMutate(RuleMatcher
&Rule
,
2077 const InstructionMatcher
*Insn
) const {
2081 if (OperandRenderers
.size() != Insn
->getNumOperands())
2084 for (const auto &Renderer
: enumerate(OperandRenderers
)) {
2085 if (const auto *Copy
= dyn_cast
<CopyRenderer
>(&*Renderer
.value())) {
2086 const OperandMatcher
&OM
=
2087 Rule
.getOperandMatcher(Copy
->getSymbolicName());
2088 if (Insn
!= &OM
.getInstructionMatcher() ||
2089 OM
.getOpIdx() != Renderer
.index())
2098 void BuildMIAction::chooseInsnToMutate(RuleMatcher
&Rule
) {
2099 for (auto *MutateCandidate
: Rule
.mutatable_insns()) {
2100 if (canMutate(Rule
, MutateCandidate
)) {
2101 // Take the first one we're offered that we're able to mutate.
2102 Rule
.reserveInsnMatcherForMutation(MutateCandidate
);
2103 Matched
= MutateCandidate
;
2109 void BuildMIAction::emitActionOpcodes(MatchTable
&Table
,
2110 RuleMatcher
&Rule
) const {
2111 const auto AddMIFlags
= [&]() {
2112 for (const InstructionMatcher
*IM
: CopiedFlags
) {
2113 Table
<< MatchTable::Opcode("GIR_CopyMIFlags")
2114 << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
)
2115 << MatchTable::Comment("OldInsnID")
2116 << MatchTable::ULEB128Value(IM
->getInsnVarID())
2117 << MatchTable::LineBreak
;
2120 if (!SetFlags
.empty()) {
2121 Table
<< MatchTable::Opcode("GIR_SetMIFlags")
2122 << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
)
2123 << MatchTable::NamedValue(4, join(SetFlags
, " | "))
2124 << MatchTable::LineBreak
;
2127 if (!UnsetFlags
.empty()) {
2128 Table
<< MatchTable::Opcode("GIR_UnsetMIFlags")
2129 << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
)
2130 << MatchTable::NamedValue(4, join(UnsetFlags
, " | "))
2131 << MatchTable::LineBreak
;
2136 assert(canMutate(Rule
, Matched
) &&
2137 "Arranged to mutate an insn that isn't mutatable");
2139 unsigned RecycleInsnID
= Rule
.getInsnVarID(*Matched
);
2140 Table
<< MatchTable::Opcode("GIR_MutateOpcode")
2141 << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
)
2142 << MatchTable::Comment("RecycleInsnID")
2143 << MatchTable::ULEB128Value(RecycleInsnID
)
2144 << MatchTable::Comment("Opcode")
2145 << MatchTable::NamedValue(2, I
->Namespace
, I
->TheDef
->getName())
2146 << MatchTable::LineBreak
;
2148 if (!I
->ImplicitDefs
.empty() || !I
->ImplicitUses
.empty()) {
2149 for (auto *Def
: I
->ImplicitDefs
) {
2150 auto Namespace
= Def
->getValue("Namespace")
2151 ? Def
->getValueAsString("Namespace")
2153 const bool IsDead
= DeadImplicitDefs
.contains(Def
);
2154 Table
<< MatchTable::Opcode("GIR_AddImplicitDef")
2155 << MatchTable::Comment("InsnID")
2156 << MatchTable::ULEB128Value(InsnID
)
2157 << MatchTable::NamedValue(2, Namespace
, Def
->getName())
2158 << (IsDead
? MatchTable::NamedValue(2, "RegState", "Dead")
2159 : MatchTable::IntValue(2, 0))
2160 << MatchTable::LineBreak
;
2162 for (auto *Use
: I
->ImplicitUses
) {
2163 auto Namespace
= Use
->getValue("Namespace")
2164 ? Use
->getValueAsString("Namespace")
2166 Table
<< MatchTable::Opcode("GIR_AddImplicitUse")
2167 << MatchTable::Comment("InsnID")
2168 << MatchTable::ULEB128Value(InsnID
)
2169 << MatchTable::NamedValue(2, Namespace
, Use
->getName())
2170 << MatchTable::LineBreak
;
2176 // Mark the mutated instruction as erased.
2177 Rule
.tryEraseInsnID(RecycleInsnID
);
2181 // TODO: Simple permutation looks like it could be almost as common as
2182 // mutation due to commutative operations.
2184 Table
<< MatchTable::Opcode("GIR_BuildMI") << MatchTable::Comment("InsnID")
2185 << MatchTable::ULEB128Value(InsnID
) << MatchTable::Comment("Opcode")
2186 << MatchTable::NamedValue(2, I
->Namespace
, I
->TheDef
->getName())
2187 << MatchTable::LineBreak
;
2188 for (const auto &Renderer
: OperandRenderers
)
2189 Renderer
->emitRenderOpcodes(Table
, Rule
);
2191 for (auto [OpIdx
, Def
] : enumerate(I
->ImplicitDefs
)) {
2193 Def
->getValue("Namespace") ? Def
->getValueAsString("Namespace") : "";
2194 if (DeadImplicitDefs
.contains(Def
)) {
2196 << MatchTable::Opcode("GIR_SetImplicitDefDead")
2197 << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
)
2198 << MatchTable::Comment(
2199 ("OpIdx for " + Namespace
+ "::" + Def
->getName() + "").str())
2200 << MatchTable::ULEB128Value(OpIdx
) << MatchTable::LineBreak
;
2204 if (I
->mayLoad
|| I
->mayStore
) {
2205 // Emit the ID's for all the instructions that are matched by this rule.
2206 // TODO: Limit this to matched instructions that mayLoad/mayStore or have
2207 // some other means of having a memoperand. Also limit this to
2208 // emitted instructions that expect to have a memoperand too. For
2209 // example, (G_SEXT (G_LOAD x)) that results in separate load and
2210 // sign-extend instructions shouldn't put the memoperand on the
2211 // sign-extend since it has no effect there.
2213 std::vector
<unsigned> MergeInsnIDs
;
2214 for (const auto &IDMatcherPair
: Rule
.defined_insn_vars())
2215 MergeInsnIDs
.push_back(IDMatcherPair
.second
);
2216 llvm::sort(MergeInsnIDs
);
2218 Table
<< MatchTable::Opcode("GIR_MergeMemOperands")
2219 << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
)
2220 << MatchTable::Comment("NumInsns")
2221 << MatchTable::IntValue(1, MergeInsnIDs
.size())
2222 << MatchTable::Comment("MergeInsnID's");
2223 for (const auto &MergeInsnID
: MergeInsnIDs
)
2224 Table
<< MatchTable::ULEB128Value(MergeInsnID
);
2225 Table
<< MatchTable::LineBreak
;
2231 //===- BuildConstantAction ------------------------------------------------===//
2233 void BuildConstantAction::emitActionOpcodes(MatchTable
&Table
,
2234 RuleMatcher
&Rule
) const {
2235 Table
<< MatchTable::Opcode("GIR_BuildConstant")
2236 << MatchTable::Comment("TempRegID")
2237 << MatchTable::ULEB128Value(TempRegID
) << MatchTable::Comment("Val")
2238 << MatchTable::IntValue(8, Val
) << MatchTable::LineBreak
;
2241 //===- EraseInstAction ----------------------------------------------------===//
2243 void EraseInstAction::emitActionOpcodes(MatchTable
&Table
, RuleMatcher
&Rule
,
2245 // Avoid erasing the same inst twice.
2246 if (!Rule
.tryEraseInsnID(InsnID
))
2249 Table
<< MatchTable::Opcode("GIR_EraseFromParent")
2250 << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
)
2251 << MatchTable::LineBreak
;
2254 void EraseInstAction::emitActionOpcodes(MatchTable
&Table
,
2255 RuleMatcher
&Rule
) const {
2256 emitActionOpcodes(Table
, Rule
, InsnID
);
2259 //===- ReplaceRegAction ---------------------------------------------------===//
2261 void ReplaceRegAction::emitAdditionalPredicates(MatchTable
&Table
,
2262 RuleMatcher
&Rule
) const {
2263 if (TempRegID
!= (unsigned)-1)
2266 Table
<< MatchTable::Opcode("GIM_CheckCanReplaceReg")
2267 << MatchTable::Comment("OldInsnID")
2268 << MatchTable::ULEB128Value(OldInsnID
)
2269 << MatchTable::Comment("OldOpIdx") << MatchTable::ULEB128Value(OldOpIdx
)
2270 << MatchTable::Comment("NewInsnId")
2271 << MatchTable::ULEB128Value(NewInsnId
)
2272 << MatchTable::Comment("NewOpIdx") << MatchTable::ULEB128Value(NewOpIdx
)
2273 << MatchTable::LineBreak
;
2276 void ReplaceRegAction::emitActionOpcodes(MatchTable
&Table
,
2277 RuleMatcher
&Rule
) const {
2278 if (TempRegID
!= (unsigned)-1) {
2279 Table
<< MatchTable::Opcode("GIR_ReplaceRegWithTempReg")
2280 << MatchTable::Comment("OldInsnID")
2281 << MatchTable::ULEB128Value(OldInsnID
)
2282 << MatchTable::Comment("OldOpIdx")
2283 << MatchTable::ULEB128Value(OldOpIdx
)
2284 << MatchTable::Comment("TempRegID")
2285 << MatchTable::ULEB128Value(TempRegID
) << MatchTable::LineBreak
;
2287 Table
<< MatchTable::Opcode("GIR_ReplaceReg")
2288 << MatchTable::Comment("OldInsnID")
2289 << MatchTable::ULEB128Value(OldInsnID
)
2290 << MatchTable::Comment("OldOpIdx")
2291 << MatchTable::ULEB128Value(OldOpIdx
)
2292 << MatchTable::Comment("NewInsnId")
2293 << MatchTable::ULEB128Value(NewInsnId
)
2294 << MatchTable::Comment("NewOpIdx")
2295 << MatchTable::ULEB128Value(NewOpIdx
) << MatchTable::LineBreak
;
2299 //===- ConstrainOperandToRegClassAction -----------------------------------===//
2301 void ConstrainOperandToRegClassAction::emitActionOpcodes(
2302 MatchTable
&Table
, RuleMatcher
&Rule
) const {
2303 Table
<< MatchTable::Opcode("GIR_ConstrainOperandRC")
2304 << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID
)
2305 << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx
)
2306 << MatchTable::NamedValue(2, RC
.getQualifiedIdName())
2307 << MatchTable::LineBreak
;
2310 //===- MakeTempRegisterAction ---------------------------------------------===//
2312 void MakeTempRegisterAction::emitActionOpcodes(MatchTable
&Table
,
2313 RuleMatcher
&Rule
) const {
2314 Table
<< MatchTable::Opcode("GIR_MakeTempReg")
2315 << MatchTable::Comment("TempRegID")
2316 << MatchTable::ULEB128Value(TempRegID
) << MatchTable::Comment("TypeID")
2317 << Ty
<< MatchTable::LineBreak
;