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/ScopedPrinter.h"
15 #include "llvm/Support/raw_ostream.h"
16 #include "llvm/TableGen/Error.h"
18 #define DEBUG_TYPE "gi-match-table"
20 STATISTIC(NumPatternEmitted
, "Number of patterns emitted");
27 Error
failUnsupported(const Twine
&Reason
) {
28 return make_error
<StringError
>(Reason
, inconvertibleErrorCode());
31 /// Get the name of the enum value used to number the predicate function.
32 std::string
getEnumNameForPredicate(const TreePredicateFn
&Predicate
) {
33 if (Predicate
.hasGISelPredicateCode())
34 return "GICXXPred_MI_" + Predicate
.getFnName();
35 return "GICXXPred_" + Predicate
.getImmTypeIdentifier().str() + "_" +
36 Predicate
.getFnName();
39 std::string
getMatchOpcodeForImmPredicate(const TreePredicateFn
&Predicate
) {
40 return "GIM_Check" + Predicate
.getImmTypeIdentifier().str() + "ImmPredicate";
44 //===- Helpers ------------------------------------------------------------===//
46 std::string
getNameForFeatureBitset(const std::vector
<Record
*> &FeatureBitset
,
48 std::string Name
= "GIFBS";
49 for (const auto &Feature
: FeatureBitset
)
50 Name
+= ("_" + Feature
->getName()).str();
52 Name
+= ("_HwMode" + std::to_string(HwModeIdx
));
56 template <class GroupT
>
57 std::vector
<Matcher
*>
58 optimizeRules(ArrayRef
<Matcher
*> Rules
,
59 std::vector
<std::unique_ptr
<Matcher
>> &MatcherStorage
) {
61 std::vector
<Matcher
*> OptRules
;
62 std::unique_ptr
<GroupT
> CurrentGroup
= std::make_unique
<GroupT
>();
63 assert(CurrentGroup
->empty() && "Newly created group isn't empty!");
64 unsigned NumGroups
= 0;
66 auto ProcessCurrentGroup
= [&]() {
67 if (CurrentGroup
->empty())
68 // An empty group is good to be reused:
71 // If the group isn't large enough to provide any benefit, move all the
72 // added rules out of it and make sure to re-create the group to properly
74 if (CurrentGroup
->size() < 2)
75 append_range(OptRules
, CurrentGroup
->matchers());
77 CurrentGroup
->finalize();
78 OptRules
.push_back(CurrentGroup
.get());
79 MatcherStorage
.emplace_back(std::move(CurrentGroup
));
82 CurrentGroup
= std::make_unique
<GroupT
>();
84 for (Matcher
*Rule
: Rules
) {
85 // Greedily add as many matchers as possible to the current group:
86 if (CurrentGroup
->addMatcher(*Rule
))
89 ProcessCurrentGroup();
90 assert(CurrentGroup
->empty() && "A group wasn't properly re-initialized");
92 // Try to add the pending matcher to a newly created empty group:
93 if (!CurrentGroup
->addMatcher(*Rule
))
94 // If we couldn't add the matcher to an empty group, that group type
95 // doesn't support that kind of matchers at all, so just skip it:
96 OptRules
.push_back(Rule
);
98 ProcessCurrentGroup();
100 LLVM_DEBUG(dbgs() << "NumGroups: " << NumGroups
<< "\n");
102 assert(CurrentGroup
->empty() && "The last group wasn't properly processed");
106 template std::vector
<Matcher
*> optimizeRules
<GroupMatcher
>(
107 ArrayRef
<Matcher
*> Rules
,
108 std::vector
<std::unique_ptr
<Matcher
>> &MatcherStorage
);
110 template std::vector
<Matcher
*> optimizeRules
<SwitchMatcher
>(
111 ArrayRef
<Matcher
*> Rules
,
112 std::vector
<std::unique_ptr
<Matcher
>> &MatcherStorage
);
114 //===- Global Data --------------------------------------------------------===//
116 std::set
<LLTCodeGen
> KnownTypes
;
118 //===- MatchTableRecord ---------------------------------------------------===//
120 void MatchTableRecord::emit(raw_ostream
&OS
, bool LineBreakIsNextAfterThis
,
121 const MatchTable
&Table
) const {
122 bool UseLineComment
=
123 LineBreakIsNextAfterThis
|| (Flags
& MTRF_LineBreakFollows
);
124 if (Flags
& (MTRF_JumpTarget
| MTRF_CommaFollows
))
125 UseLineComment
= false;
127 if (Flags
& MTRF_Comment
)
128 OS
<< (UseLineComment
? "// " : "/*");
131 if (Flags
& MTRF_Label
)
132 OS
<< ": @" << Table
.getLabelIndex(LabelID
);
134 if ((Flags
& MTRF_Comment
) && !UseLineComment
)
137 if (Flags
& MTRF_JumpTarget
) {
138 if (Flags
& MTRF_Comment
)
140 OS
<< Table
.getLabelIndex(LabelID
);
143 if (Flags
& MTRF_CommaFollows
) {
145 if (!LineBreakIsNextAfterThis
&& !(Flags
& MTRF_LineBreakFollows
))
149 if (Flags
& MTRF_LineBreakFollows
)
153 //===- MatchTable ---------------------------------------------------------===//
155 MatchTableRecord
MatchTable::LineBreak
= {
156 std::nullopt
, "" /* Emit String */, 0 /* Elements */,
157 MatchTableRecord::MTRF_LineBreakFollows
};
159 MatchTableRecord
MatchTable::Comment(StringRef Comment
) {
160 return MatchTableRecord(std::nullopt
, Comment
, 0,
161 MatchTableRecord::MTRF_Comment
);
164 MatchTableRecord
MatchTable::Opcode(StringRef Opcode
, int IndentAdjust
) {
165 unsigned ExtraFlags
= 0;
166 if (IndentAdjust
> 0)
167 ExtraFlags
|= MatchTableRecord::MTRF_Indent
;
168 if (IndentAdjust
< 0)
169 ExtraFlags
|= MatchTableRecord::MTRF_Outdent
;
171 return MatchTableRecord(std::nullopt
, Opcode
, 1,
172 MatchTableRecord::MTRF_CommaFollows
| ExtraFlags
);
175 MatchTableRecord
MatchTable::NamedValue(StringRef NamedValue
) {
176 return MatchTableRecord(std::nullopt
, NamedValue
, 1,
177 MatchTableRecord::MTRF_CommaFollows
);
180 MatchTableRecord
MatchTable::NamedValue(StringRef NamedValue
,
182 return MatchTableRecord(std::nullopt
, NamedValue
, 1,
183 MatchTableRecord::MTRF_CommaFollows
, RawValue
);
186 MatchTableRecord
MatchTable::NamedValue(StringRef Namespace
,
187 StringRef NamedValue
) {
188 return MatchTableRecord(std::nullopt
, (Namespace
+ "::" + NamedValue
).str(),
189 1, MatchTableRecord::MTRF_CommaFollows
);
192 MatchTableRecord
MatchTable::NamedValue(StringRef Namespace
,
193 StringRef NamedValue
,
195 return MatchTableRecord(std::nullopt
, (Namespace
+ "::" + NamedValue
).str(),
196 1, MatchTableRecord::MTRF_CommaFollows
, RawValue
);
199 MatchTableRecord
MatchTable::IntValue(int64_t IntValue
) {
200 return MatchTableRecord(std::nullopt
, llvm::to_string(IntValue
), 1,
201 MatchTableRecord::MTRF_CommaFollows
);
204 MatchTableRecord
MatchTable::Label(unsigned LabelID
) {
205 return MatchTableRecord(LabelID
, "Label " + llvm::to_string(LabelID
), 0,
206 MatchTableRecord::MTRF_Label
|
207 MatchTableRecord::MTRF_Comment
|
208 MatchTableRecord::MTRF_LineBreakFollows
);
211 MatchTableRecord
MatchTable::JumpTarget(unsigned LabelID
) {
212 return MatchTableRecord(LabelID
, "Label " + llvm::to_string(LabelID
), 1,
213 MatchTableRecord::MTRF_JumpTarget
|
214 MatchTableRecord::MTRF_Comment
|
215 MatchTableRecord::MTRF_CommaFollows
);
218 void MatchTable::emitUse(raw_ostream
&OS
) const { OS
<< "MatchTable" << ID
; }
220 void MatchTable::emitDeclaration(raw_ostream
&OS
) const {
221 unsigned Indentation
= 4;
222 OS
<< " constexpr static int64_t MatchTable" << ID
<< "[] = {";
223 LineBreak
.emit(OS
, true, *this);
224 OS
<< std::string(Indentation
, ' ');
226 for (auto I
= Contents
.begin(), E
= Contents
.end(); I
!= E
; ++I
) {
227 bool LineBreakIsNext
= false;
228 const auto &NextI
= std::next(I
);
231 if (NextI
->EmitStr
== "" &&
232 NextI
->Flags
== MatchTableRecord::MTRF_LineBreakFollows
)
233 LineBreakIsNext
= true;
236 if (I
->Flags
& MatchTableRecord::MTRF_Indent
)
239 I
->emit(OS
, LineBreakIsNext
, *this);
240 if (I
->Flags
& MatchTableRecord::MTRF_LineBreakFollows
)
241 OS
<< std::string(Indentation
, ' ');
243 if (I
->Flags
& MatchTableRecord::MTRF_Outdent
)
249 MatchTable
MatchTable::buildTable(ArrayRef
<Matcher
*> Rules
, bool WithCoverage
,
251 MatchTable
Table(WithCoverage
, IsCombiner
);
252 for (Matcher
*Rule
: Rules
)
255 return Table
<< MatchTable::Opcode("GIM_Reject") << MatchTable::LineBreak
;
258 //===- LLTCodeGen ---------------------------------------------------------===//
260 std::string
LLTCodeGen::getCxxEnumValue() const {
262 raw_string_ostream
OS(Str
);
264 emitCxxEnumValue(OS
);
268 void LLTCodeGen::emitCxxEnumValue(raw_ostream
&OS
) const {
270 OS
<< "GILLT_s" << Ty
.getSizeInBits();
274 OS
<< (Ty
.isScalable() ? "GILLT_nxv" : "GILLT_v")
275 << Ty
.getElementCount().getKnownMinValue() << "s"
276 << Ty
.getScalarSizeInBits();
279 if (Ty
.isPointer()) {
280 OS
<< "GILLT_p" << Ty
.getAddressSpace();
281 if (Ty
.getSizeInBits() > 0)
282 OS
<< "s" << Ty
.getSizeInBits();
285 llvm_unreachable("Unhandled LLT");
288 void LLTCodeGen::emitCxxConstructorCall(raw_ostream
&OS
) const {
290 OS
<< "LLT::scalar(" << Ty
.getSizeInBits() << ")";
295 << (Ty
.isScalable() ? "ElementCount::getScalable("
296 : "ElementCount::getFixed(")
297 << Ty
.getElementCount().getKnownMinValue() << "), "
298 << Ty
.getScalarSizeInBits() << ")";
301 if (Ty
.isPointer() && Ty
.getSizeInBits() > 0) {
302 OS
<< "LLT::pointer(" << Ty
.getAddressSpace() << ", " << Ty
.getSizeInBits()
306 llvm_unreachable("Unhandled LLT");
309 /// This ordering is used for std::unique() and llvm::sort(). There's no
310 /// particular logic behind the order but either A < B or B < A must be
312 bool LLTCodeGen::operator<(const LLTCodeGen
&Other
) const {
313 if (Ty
.isValid() != Other
.Ty
.isValid())
314 return Ty
.isValid() < Other
.Ty
.isValid();
318 if (Ty
.isVector() != Other
.Ty
.isVector())
319 return Ty
.isVector() < Other
.Ty
.isVector();
320 if (Ty
.isScalar() != Other
.Ty
.isScalar())
321 return Ty
.isScalar() < Other
.Ty
.isScalar();
322 if (Ty
.isPointer() != Other
.Ty
.isPointer())
323 return Ty
.isPointer() < Other
.Ty
.isPointer();
325 if (Ty
.isPointer() && Ty
.getAddressSpace() != Other
.Ty
.getAddressSpace())
326 return Ty
.getAddressSpace() < Other
.Ty
.getAddressSpace();
328 if (Ty
.isVector() && Ty
.getElementCount() != Other
.Ty
.getElementCount())
329 return std::make_tuple(Ty
.isScalable(),
330 Ty
.getElementCount().getKnownMinValue()) <
331 std::make_tuple(Other
.Ty
.isScalable(),
332 Other
.Ty
.getElementCount().getKnownMinValue());
334 assert((!Ty
.isVector() || Ty
.isScalable() == Other
.Ty
.isScalable()) &&
335 "Unexpected mismatch of scalable property");
337 ? std::make_tuple(Ty
.isScalable(),
338 Ty
.getSizeInBits().getKnownMinValue()) <
339 std::make_tuple(Other
.Ty
.isScalable(),
340 Other
.Ty
.getSizeInBits().getKnownMinValue())
341 : Ty
.getSizeInBits().getFixedValue() <
342 Other
.Ty
.getSizeInBits().getFixedValue();
345 //===- LLTCodeGen Helpers -------------------------------------------------===//
347 std::optional
<LLTCodeGen
> MVTToLLT(MVT::SimpleValueType SVT
) {
350 if (VT
.isVector() && !VT
.getVectorElementCount().isScalar())
352 LLT::vector(VT
.getVectorElementCount(), VT
.getScalarSizeInBits()));
354 if (VT
.isInteger() || VT
.isFloatingPoint())
355 return LLTCodeGen(LLT::scalar(VT
.getSizeInBits()));
360 //===- Matcher ------------------------------------------------------------===//
362 void Matcher::optimize() {}
364 Matcher::~Matcher() {}
366 //===- GroupMatcher -------------------------------------------------------===//
368 bool GroupMatcher::candidateConditionMatches(
369 const PredicateMatcher
&Predicate
) const {
372 // Sharing predicates for nested instructions is not supported yet as we
373 // currently don't hoist the GIM_RecordInsn's properly, therefore we can
374 // only work on the original root instruction (InsnVarID == 0):
375 if (Predicate
.getInsnVarID() != 0)
377 // ... otherwise an empty group can handle any predicate with no specific
382 const Matcher
&Representative
= **Matchers
.begin();
383 const auto &RepresentativeCondition
= Representative
.getFirstCondition();
384 // ... if not empty, the group can only accomodate matchers with the exact
385 // same first condition:
386 return Predicate
.isIdentical(RepresentativeCondition
);
389 bool GroupMatcher::addMatcher(Matcher
&Candidate
) {
390 if (!Candidate
.hasFirstCondition())
393 const PredicateMatcher
&Predicate
= Candidate
.getFirstCondition();
394 if (!candidateConditionMatches(Predicate
))
397 Matchers
.push_back(&Candidate
);
401 void GroupMatcher::finalize() {
402 assert(Conditions
.empty() && "Already finalized?");
406 Matcher
&FirstRule
= **Matchers
.begin();
408 // All the checks are expected to succeed during the first iteration:
409 for (const auto &Rule
: Matchers
)
410 if (!Rule
->hasFirstCondition())
412 const auto &FirstCondition
= FirstRule
.getFirstCondition();
413 for (unsigned I
= 1, E
= Matchers
.size(); I
< E
; ++I
)
414 if (!Matchers
[I
]->getFirstCondition().isIdentical(FirstCondition
))
417 Conditions
.push_back(FirstRule
.popFirstCondition());
418 for (unsigned I
= 1, E
= Matchers
.size(); I
< E
; ++I
)
419 Matchers
[I
]->popFirstCondition();
423 void GroupMatcher::emit(MatchTable
&Table
) {
424 unsigned LabelID
= ~0U;
425 if (!Conditions
.empty()) {
426 LabelID
= Table
.allocateLabelID();
427 Table
<< MatchTable::Opcode("GIM_Try", +1)
428 << MatchTable::Comment("On fail goto")
429 << MatchTable::JumpTarget(LabelID
) << MatchTable::LineBreak
;
431 for (auto &Condition
: Conditions
)
432 Condition
->emitPredicateOpcodes(
433 Table
, *static_cast<RuleMatcher
*>(*Matchers
.begin()));
435 for (const auto &M
: Matchers
)
439 if (!Conditions
.empty())
440 Table
<< MatchTable::Opcode("GIM_Reject", -1) << MatchTable::LineBreak
441 << MatchTable::Label(LabelID
);
444 void GroupMatcher::optimize() {
445 // Make sure we only sort by a specific predicate within a range of rules that
446 // all have that predicate checked against a specific value (not a wildcard):
447 auto F
= Matchers
.begin();
449 auto E
= Matchers
.end();
452 auto *R
= static_cast<RuleMatcher
*>(*T
);
453 if (!R
->getFirstConditionAsRootType().get().isValid())
457 std::stable_sort(F
, T
, [](Matcher
*A
, Matcher
*B
) {
458 auto *L
= static_cast<RuleMatcher
*>(A
);
459 auto *R
= static_cast<RuleMatcher
*>(B
);
460 return L
->getFirstConditionAsRootType() <
461 R
->getFirstConditionAsRootType();
466 optimizeRules
<GroupMatcher
>(Matchers
, MatcherStorage
).swap(Matchers
);
467 optimizeRules
<SwitchMatcher
>(Matchers
, MatcherStorage
).swap(Matchers
);
470 //===- SwitchMatcher ------------------------------------------------------===//
472 bool SwitchMatcher::isSupportedPredicateType(const PredicateMatcher
&P
) {
473 return isa
<InstructionOpcodeMatcher
>(P
) || isa
<LLTOperandMatcher
>(P
);
476 bool SwitchMatcher::candidateConditionMatches(
477 const PredicateMatcher
&Predicate
) const {
480 // Sharing predicates for nested instructions is not supported yet as we
481 // currently don't hoist the GIM_RecordInsn's properly, therefore we can
482 // only work on the original root instruction (InsnVarID == 0):
483 if (Predicate
.getInsnVarID() != 0)
485 // ... while an attempt to add even a root matcher to an empty SwitchMatcher
486 // could fail as not all the types of conditions are supported:
487 if (!isSupportedPredicateType(Predicate
))
489 // ... or the condition might not have a proper implementation of
490 // getValue() / isIdenticalDownToValue() yet:
491 if (!Predicate
.hasValue())
493 // ... otherwise an empty Switch can accomodate the condition with no
494 // further requirements:
498 const Matcher
&CaseRepresentative
= **Matchers
.begin();
499 const auto &RepresentativeCondition
= CaseRepresentative
.getFirstCondition();
500 // Switch-cases must share the same kind of condition and path to the value it
502 if (!Predicate
.isIdenticalDownToValue(RepresentativeCondition
))
505 const auto Value
= Predicate
.getValue();
506 // ... but be unique with respect to the actual value they check:
507 return Values
.count(Value
) == 0;
510 bool SwitchMatcher::addMatcher(Matcher
&Candidate
) {
511 if (!Candidate
.hasFirstCondition())
514 const PredicateMatcher
&Predicate
= Candidate
.getFirstCondition();
515 if (!candidateConditionMatches(Predicate
))
517 const auto Value
= Predicate
.getValue();
518 Values
.insert(Value
);
520 Matchers
.push_back(&Candidate
);
524 void SwitchMatcher::finalize() {
525 assert(Condition
== nullptr && "Already finalized");
526 assert(Values
.size() == Matchers
.size() && "Broken SwitchMatcher");
530 llvm::stable_sort(Matchers
, [](const Matcher
*L
, const Matcher
*R
) {
531 return L
->getFirstCondition().getValue() <
532 R
->getFirstCondition().getValue();
534 Condition
= Matchers
[0]->popFirstCondition();
535 for (unsigned I
= 1, E
= Values
.size(); I
< E
; ++I
)
536 Matchers
[I
]->popFirstCondition();
539 void SwitchMatcher::emitPredicateSpecificOpcodes(const PredicateMatcher
&P
,
541 assert(isSupportedPredicateType(P
) && "Predicate type is not supported");
543 if (const auto *Condition
= dyn_cast
<InstructionOpcodeMatcher
>(&P
)) {
544 Table
<< MatchTable::Opcode("GIM_SwitchOpcode") << MatchTable::Comment("MI")
545 << MatchTable::IntValue(Condition
->getInsnVarID());
548 if (const auto *Condition
= dyn_cast
<LLTOperandMatcher
>(&P
)) {
549 Table
<< MatchTable::Opcode("GIM_SwitchType") << MatchTable::Comment("MI")
550 << MatchTable::IntValue(Condition
->getInsnVarID())
551 << MatchTable::Comment("Op")
552 << MatchTable::IntValue(Condition
->getOpIdx());
556 llvm_unreachable("emitPredicateSpecificOpcodes is broken: can not handle a "
557 "predicate type that is claimed to be supported");
560 void SwitchMatcher::emit(MatchTable
&Table
) {
561 assert(Values
.size() == Matchers
.size() && "Broken SwitchMatcher");
564 assert(Condition
!= nullptr &&
565 "Broken SwitchMatcher, hasn't been finalized?");
567 std::vector
<unsigned> LabelIDs(Values
.size());
568 std::generate(LabelIDs
.begin(), LabelIDs
.end(),
569 [&Table
]() { return Table
.allocateLabelID(); });
570 const unsigned Default
= Table
.allocateLabelID();
572 const int64_t LowerBound
= Values
.begin()->getRawValue();
573 const int64_t UpperBound
= Values
.rbegin()->getRawValue() + 1;
575 emitPredicateSpecificOpcodes(*Condition
, Table
);
577 Table
<< MatchTable::Comment("[") << MatchTable::IntValue(LowerBound
)
578 << MatchTable::IntValue(UpperBound
) << MatchTable::Comment(")")
579 << MatchTable::Comment("default:") << MatchTable::JumpTarget(Default
);
581 int64_t J
= LowerBound
;
582 auto VI
= Values
.begin();
583 for (unsigned I
= 0, E
= Values
.size(); I
< E
; ++I
) {
585 while (J
++ < V
.getRawValue())
586 Table
<< MatchTable::IntValue(0);
588 Table
<< MatchTable::LineBreak
<< V
<< MatchTable::JumpTarget(LabelIDs
[I
]);
590 Table
<< MatchTable::LineBreak
;
592 for (unsigned I
= 0, E
= Values
.size(); I
< E
; ++I
) {
593 Table
<< MatchTable::Label(LabelIDs
[I
]);
594 Matchers
[I
]->emit(Table
);
595 Table
<< MatchTable::Opcode("GIM_Reject") << MatchTable::LineBreak
;
597 Table
<< MatchTable::Label(Default
);
600 //===- RuleMatcher --------------------------------------------------------===//
602 uint64_t RuleMatcher::NextRuleID
= 0;
604 StringRef
RuleMatcher::getOpcode() const {
605 return Matchers
.front()->getOpcode();
608 unsigned RuleMatcher::getNumOperands() const {
609 return Matchers
.front()->getNumOperands();
612 LLTCodeGen
RuleMatcher::getFirstConditionAsRootType() {
613 InstructionMatcher
&InsnMatcher
= *Matchers
.front();
614 if (!InsnMatcher
.predicates_empty())
616 dyn_cast
<LLTOperandMatcher
>(&**InsnMatcher
.predicates_begin()))
617 if (TM
->getInsnVarID() == 0 && TM
->getOpIdx() == 0)
622 void RuleMatcher::optimize() {
623 for (auto &Item
: InsnVariableIDs
) {
624 InstructionMatcher
&InsnMatcher
= *Item
.first
;
625 for (auto &OM
: InsnMatcher
.operands()) {
626 // Complex Patterns are usually expensive and they relatively rarely fail
627 // on their own: more often we end up throwing away all the work done by a
628 // matching part of a complex pattern because some other part of the
629 // enclosing pattern didn't match. All of this makes it beneficial to
630 // delay complex patterns until the very end of the rule matching,
631 // especially for targets having lots of complex patterns.
632 for (auto &OP
: OM
->predicates())
633 if (isa
<ComplexPatternOperandMatcher
>(OP
))
634 EpilogueMatchers
.emplace_back(std::move(OP
));
635 OM
->eraseNullPredicates();
637 InsnMatcher
.optimize();
639 llvm::sort(EpilogueMatchers
, [](const std::unique_ptr
<PredicateMatcher
> &L
,
640 const std::unique_ptr
<PredicateMatcher
> &R
) {
641 return std::make_tuple(L
->getKind(), L
->getInsnVarID(), L
->getOpIdx()) <
642 std::make_tuple(R
->getKind(), R
->getInsnVarID(), R
->getOpIdx());
646 bool RuleMatcher::hasFirstCondition() const {
647 if (insnmatchers_empty())
649 InstructionMatcher
&Matcher
= insnmatchers_front();
650 if (!Matcher
.predicates_empty())
652 for (auto &OM
: Matcher
.operands())
653 for (auto &OP
: OM
->predicates())
654 if (!isa
<InstructionOperandMatcher
>(OP
))
659 const PredicateMatcher
&RuleMatcher::getFirstCondition() const {
660 assert(!insnmatchers_empty() &&
661 "Trying to get a condition from an empty RuleMatcher");
663 InstructionMatcher
&Matcher
= insnmatchers_front();
664 if (!Matcher
.predicates_empty())
665 return **Matcher
.predicates_begin();
666 // If there is no more predicate on the instruction itself, look at its
668 for (auto &OM
: Matcher
.operands())
669 for (auto &OP
: OM
->predicates())
670 if (!isa
<InstructionOperandMatcher
>(OP
))
673 llvm_unreachable("Trying to get a condition from an InstructionMatcher with "
677 std::unique_ptr
<PredicateMatcher
> RuleMatcher::popFirstCondition() {
678 assert(!insnmatchers_empty() &&
679 "Trying to pop a condition from an empty RuleMatcher");
681 InstructionMatcher
&Matcher
= insnmatchers_front();
682 if (!Matcher
.predicates_empty())
683 return Matcher
.predicates_pop_front();
684 // If there is no more predicate on the instruction itself, look at its
686 for (auto &OM
: Matcher
.operands())
687 for (auto &OP
: OM
->predicates())
688 if (!isa
<InstructionOperandMatcher
>(OP
)) {
689 std::unique_ptr
<PredicateMatcher
> Result
= std::move(OP
);
690 OM
->eraseNullPredicates();
694 llvm_unreachable("Trying to pop a condition from an InstructionMatcher with "
698 GISelFlags
RuleMatcher::updateGISelFlag(GISelFlags CurFlags
, const Record
*R
,
700 GISelFlags FlagBit
) {
701 // If the value of a flag is unset, ignore it.
702 // If it's set, it always takes precedence over the existing value so
703 // clear/set the corresponding bit.
705 bool Value
= R
->getValueAsBitOrUnset("GIIgnoreCopies", Unset
);
707 return Value
? (CurFlags
| FlagBit
) : (CurFlags
& ~FlagBit
);
711 SaveAndRestore
<GISelFlags
> RuleMatcher::setGISelFlags(const Record
*R
) {
712 if (!R
|| !R
->isSubClassOf("GISelFlags"))
713 return {Flags
, Flags
};
715 assert((R
->isSubClassOf("PatFrags") || R
->isSubClassOf("Pattern")) &&
716 "GISelFlags is only expected on Pattern/PatFrags!");
718 GISelFlags NewFlags
=
719 updateGISelFlag(Flags
, R
, "GIIgnoreCopies", GISF_IgnoreCopies
);
720 return {Flags
, NewFlags
};
723 Error
RuleMatcher::defineComplexSubOperand(StringRef SymbolicName
,
724 Record
*ComplexPattern
,
726 unsigned SubOperandID
,
727 StringRef ParentSymbolicName
) {
728 std::string
ParentName(ParentSymbolicName
);
729 if (ComplexSubOperands
.count(SymbolicName
)) {
730 const std::string
&RecordedParentName
=
731 ComplexSubOperandsParentName
[SymbolicName
];
732 if (RecordedParentName
!= ParentName
)
733 return failUnsupported("Error: Complex suboperand " + SymbolicName
+
734 " referenced by different operands: " +
735 RecordedParentName
+ " and " + ParentName
+ ".");
736 // Complex suboperand referenced more than once from same the operand is
737 // used to generate 'same operand check'. Emitting of
738 // GIR_ComplexSubOperandRenderer for them is already handled.
739 return Error::success();
742 ComplexSubOperands
[SymbolicName
] =
743 std::make_tuple(ComplexPattern
, RendererID
, SubOperandID
);
744 ComplexSubOperandsParentName
[SymbolicName
] = ParentName
;
746 return Error::success();
749 InstructionMatcher
&RuleMatcher::addInstructionMatcher(StringRef SymbolicName
) {
750 Matchers
.emplace_back(new InstructionMatcher(*this, SymbolicName
));
751 MutatableInsns
.insert(Matchers
.back().get());
752 return *Matchers
.back();
755 void RuleMatcher::addRequiredSimplePredicate(StringRef PredName
) {
756 RequiredSimplePredicates
.push_back(PredName
.str());
759 const std::vector
<std::string
> &RuleMatcher::getRequiredSimplePredicates() {
760 return RequiredSimplePredicates
;
763 void RuleMatcher::addRequiredFeature(Record
*Feature
) {
764 RequiredFeatures
.push_back(Feature
);
767 const std::vector
<Record
*> &RuleMatcher::getRequiredFeatures() const {
768 return RequiredFeatures
;
771 unsigned RuleMatcher::implicitlyDefineInsnVar(InstructionMatcher
&Matcher
) {
772 unsigned NewInsnVarID
= NextInsnVarID
++;
773 InsnVariableIDs
[&Matcher
] = NewInsnVarID
;
777 unsigned RuleMatcher::getInsnVarID(InstructionMatcher
&InsnMatcher
) const {
778 const auto &I
= InsnVariableIDs
.find(&InsnMatcher
);
779 if (I
!= InsnVariableIDs
.end())
781 llvm_unreachable("Matched Insn was not captured in a local variable");
784 void RuleMatcher::defineOperand(StringRef SymbolicName
, OperandMatcher
&OM
) {
785 if (!DefinedOperands
.contains(SymbolicName
)) {
786 DefinedOperands
[SymbolicName
] = &OM
;
790 // If the operand is already defined, then we must ensure both references in
791 // the matcher have the exact same node.
792 RuleMatcher
&RM
= OM
.getInstructionMatcher().getRuleMatcher();
793 OM
.addPredicate
<SameOperandMatcher
>(
794 OM
.getSymbolicName(), getOperandMatcher(OM
.getSymbolicName()).getOpIdx(),
798 void RuleMatcher::definePhysRegOperand(Record
*Reg
, OperandMatcher
&OM
) {
799 if (!PhysRegOperands
.contains(Reg
)) {
800 PhysRegOperands
[Reg
] = &OM
;
806 RuleMatcher::getInstructionMatcher(StringRef SymbolicName
) const {
807 for (const auto &I
: InsnVariableIDs
)
808 if (I
.first
->getSymbolicName() == SymbolicName
)
811 ("Failed to lookup instruction " + SymbolicName
).str().c_str());
814 const OperandMatcher
&RuleMatcher::getPhysRegOperandMatcher(Record
*Reg
) const {
815 const auto &I
= PhysRegOperands
.find(Reg
);
817 if (I
== PhysRegOperands
.end()) {
818 PrintFatalError(SrcLoc
, "Register " + Reg
->getName() +
819 " was not declared in matcher");
825 OperandMatcher
&RuleMatcher::getOperandMatcher(StringRef Name
) {
826 const auto &I
= DefinedOperands
.find(Name
);
828 if (I
== DefinedOperands
.end())
829 PrintFatalError(SrcLoc
, "Operand " + Name
+ " was not declared in matcher");
834 const OperandMatcher
&RuleMatcher::getOperandMatcher(StringRef Name
) const {
835 const auto &I
= DefinedOperands
.find(Name
);
837 if (I
== DefinedOperands
.end())
838 PrintFatalError(SrcLoc
, "Operand " + Name
+ " was not declared in matcher");
843 void RuleMatcher::emit(MatchTable
&Table
) {
844 if (Matchers
.empty())
845 llvm_unreachable("Unexpected empty matcher!");
847 // The representation supports rules that require multiple roots such as:
849 // %elt0(s32) = G_LOAD %ptr
850 // %1(p0) = G_ADD %ptr, 4
851 // %elt1(s32) = G_LOAD p0 %1
852 // which could be usefully folded into:
854 // %elt0(s32), %elt1(s32) = TGT_LOAD_PAIR %ptr
855 // on some targets but we don't need to make use of that yet.
856 assert(Matchers
.size() == 1 && "Cannot handle multi-root matchers yet");
858 unsigned LabelID
= Table
.allocateLabelID();
859 Table
<< MatchTable::Opcode("GIM_Try", +1)
860 << MatchTable::Comment("On fail goto")
861 << MatchTable::JumpTarget(LabelID
)
862 << MatchTable::Comment(("Rule ID " + Twine(RuleID
) + " //").str())
863 << MatchTable::LineBreak
;
865 if (!RequiredFeatures
.empty() || HwModeIdx
>= 0) {
866 Table
<< MatchTable::Opcode("GIM_CheckFeatures")
867 << MatchTable::NamedValue(
868 getNameForFeatureBitset(RequiredFeatures
, HwModeIdx
))
869 << MatchTable::LineBreak
;
872 if (!RequiredSimplePredicates
.empty()) {
873 for (const auto &Pred
: RequiredSimplePredicates
) {
874 Table
<< MatchTable::Opcode("GIM_CheckSimplePredicate")
875 << MatchTable::NamedValue(Pred
) << MatchTable::LineBreak
;
879 Matchers
.front()->emitPredicateOpcodes(Table
, *this);
881 // Check if it's safe to replace registers.
882 for (const auto &MA
: Actions
)
883 MA
->emitAdditionalPredicates(Table
, *this);
885 // We must also check if it's safe to fold the matched instructions.
886 if (InsnVariableIDs
.size() >= 2) {
887 // Invert the map to create stable ordering (by var names)
888 SmallVector
<unsigned, 2> InsnIDs
;
889 for (const auto &Pair
: InsnVariableIDs
) {
890 // Skip the root node since it isn't moving anywhere. Everything else is
891 // sinking to meet it.
892 if (Pair
.first
== Matchers
.front().get())
895 InsnIDs
.push_back(Pair
.second
);
899 for (const auto &InsnID
: InsnIDs
) {
900 // Reject the difficult cases until we have a more accurate check.
901 Table
<< MatchTable::Opcode("GIM_CheckIsSafeToFold")
902 << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID
)
903 << MatchTable::LineBreak
;
905 // FIXME: Emit checks to determine it's _actually_ safe to fold and/or
906 // account for unsafe cases.
911 // MI0--> %2 = ... %0
912 // It's not safe to erase MI1. We currently handle this by not
913 // erasing %0 (even when it's dead).
916 // MI1--> %0 = load volatile @a
917 // %1 = load volatile @a
918 // MI0--> %2 = ... %0
919 // It's not safe to sink %0's def past %1. We currently handle
920 // this by rejecting all loads.
923 // MI1--> %0 = load @a
925 // MI0--> %2 = ... %0
926 // It's not safe to sink %0's def past %1. We currently handle
927 // this by rejecting all loads.
930 // G_CONDBR %cond, @BB1
932 // MI1--> %0 = load @a
935 // MI0--> %2 = ... %0
936 // It's not always safe to sink %0 across control flow. In this
937 // case it may introduce a memory fault. We currentl handle
938 // this by rejecting all loads.
942 for (const auto &PM
: EpilogueMatchers
)
943 PM
->emitPredicateOpcodes(Table
, *this);
945 for (const auto &MA
: Actions
)
946 MA
->emitActionOpcodes(Table
, *this);
948 assert((Table
.isWithCoverage() ? !Table
.isCombiner() : true) &&
949 "Combiner tables don't support coverage!");
950 if (Table
.isWithCoverage())
951 Table
<< MatchTable::Opcode("GIR_Coverage") << MatchTable::IntValue(RuleID
)
952 << MatchTable::LineBreak
;
953 else if (!Table
.isCombiner())
954 Table
<< MatchTable::Comment(("GIR_Coverage, " + Twine(RuleID
) + ",").str())
955 << MatchTable::LineBreak
;
957 Table
<< MatchTable::Opcode("GIR_Done", -1) << MatchTable::LineBreak
958 << MatchTable::Label(LabelID
);
962 bool RuleMatcher::isHigherPriorityThan(const RuleMatcher
&B
) const {
963 // Rules involving more match roots have higher priority.
964 if (Matchers
.size() > B
.Matchers
.size())
966 if (Matchers
.size() < B
.Matchers
.size())
969 for (auto Matcher
: zip(Matchers
, B
.Matchers
)) {
970 if (std::get
<0>(Matcher
)->isHigherPriorityThan(*std::get
<1>(Matcher
)))
972 if (std::get
<1>(Matcher
)->isHigherPriorityThan(*std::get
<0>(Matcher
)))
979 unsigned RuleMatcher::countRendererFns() const {
980 return std::accumulate(
981 Matchers
.begin(), Matchers
.end(), 0,
982 [](unsigned A
, const std::unique_ptr
<InstructionMatcher
> &Matcher
) {
983 return A
+ Matcher
->countRendererFns();
987 //===- PredicateMatcher ---------------------------------------------------===//
989 PredicateMatcher::~PredicateMatcher() {}
991 //===- OperandPredicateMatcher --------------------------------------------===//
993 OperandPredicateMatcher::~OperandPredicateMatcher() {}
995 bool OperandPredicateMatcher::isHigherPriorityThan(
996 const OperandPredicateMatcher
&B
) const {
997 // Generally speaking, an instruction is more important than an Int or a
998 // LiteralInt because it can cover more nodes but theres an exception to
999 // this. G_CONSTANT's are less important than either of those two because they
1000 // are more permissive.
1002 const InstructionOperandMatcher
*AOM
=
1003 dyn_cast
<InstructionOperandMatcher
>(this);
1004 const InstructionOperandMatcher
*BOM
=
1005 dyn_cast
<InstructionOperandMatcher
>(&B
);
1006 bool AIsConstantInsn
= AOM
&& AOM
->getInsnMatcher().isConstantInstruction();
1007 bool BIsConstantInsn
= BOM
&& BOM
->getInsnMatcher().isConstantInstruction();
1010 // The relative priorities between a G_CONSTANT and any other instruction
1011 // don't actually matter but this code is needed to ensure a strict weak
1012 // ordering. This is particularly important on Windows where the rules will
1013 // be incorrectly sorted without it.
1014 if (AIsConstantInsn
!= BIsConstantInsn
)
1015 return AIsConstantInsn
< BIsConstantInsn
;
1019 if (AOM
&& AIsConstantInsn
&& (B
.Kind
== OPM_Int
|| B
.Kind
== OPM_LiteralInt
))
1021 if (BOM
&& BIsConstantInsn
&& (Kind
== OPM_Int
|| Kind
== OPM_LiteralInt
))
1024 return Kind
< B
.Kind
;
1027 //===- SameOperandMatcher -------------------------------------------------===//
1029 void SameOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1030 RuleMatcher
&Rule
) const {
1031 const OperandMatcher
&OtherOM
= Rule
.getOperandMatcher(MatchingName
);
1032 unsigned OtherInsnVarID
= Rule
.getInsnVarID(OtherOM
.getInstructionMatcher());
1033 assert(OtherInsnVarID
== OtherOM
.getInstructionMatcher().getInsnVarID());
1034 const bool IgnoreCopies
= Flags
& GISF_IgnoreCopies
;
1035 Table
<< MatchTable::Opcode(IgnoreCopies
1036 ? "GIM_CheckIsSameOperandIgnoreCopies"
1037 : "GIM_CheckIsSameOperand")
1038 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1039 << MatchTable::Comment("OpIdx") << MatchTable::IntValue(OpIdx
)
1040 << MatchTable::Comment("OtherMI")
1041 << MatchTable::IntValue(OtherInsnVarID
)
1042 << MatchTable::Comment("OtherOpIdx")
1043 << MatchTable::IntValue(OtherOM
.getOpIdx()) << MatchTable::LineBreak
;
1046 //===- LLTOperandMatcher --------------------------------------------------===//
1048 std::map
<LLTCodeGen
, unsigned> LLTOperandMatcher::TypeIDValues
;
1050 MatchTableRecord
LLTOperandMatcher::getValue() const {
1051 const auto VI
= TypeIDValues
.find(Ty
);
1052 if (VI
== TypeIDValues
.end())
1053 return MatchTable::NamedValue(getTy().getCxxEnumValue());
1054 return MatchTable::NamedValue(getTy().getCxxEnumValue(), VI
->second
);
1057 bool LLTOperandMatcher::hasValue() const {
1058 if (TypeIDValues
.size() != KnownTypes
.size())
1059 initTypeIDValuesMap();
1060 return TypeIDValues
.count(Ty
);
1063 void LLTOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1064 RuleMatcher
&Rule
) const {
1065 Table
<< MatchTable::Opcode("GIM_CheckType") << MatchTable::Comment("MI")
1066 << MatchTable::IntValue(InsnVarID
) << MatchTable::Comment("Op")
1067 << MatchTable::IntValue(OpIdx
) << MatchTable::Comment("Type")
1068 << getValue() << MatchTable::LineBreak
;
1071 //===- PointerToAnyOperandMatcher -----------------------------------------===//
1073 void PointerToAnyOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1074 RuleMatcher
&Rule
) const {
1075 Table
<< MatchTable::Opcode("GIM_CheckPointerToAny")
1076 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1077 << MatchTable::Comment("Op") << MatchTable::IntValue(OpIdx
)
1078 << MatchTable::Comment("SizeInBits") << MatchTable::IntValue(SizeInBits
)
1079 << MatchTable::LineBreak
;
1082 //===- RecordNamedOperandMatcher ------------------------------------------===//
1084 void RecordNamedOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1085 RuleMatcher
&Rule
) const {
1086 Table
<< MatchTable::Opcode("GIM_RecordNamedOperand")
1087 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1088 << MatchTable::Comment("Op") << MatchTable::IntValue(OpIdx
)
1089 << MatchTable::Comment("StoreIdx") << MatchTable::IntValue(StoreIdx
)
1090 << MatchTable::Comment("Name : " + Name
) << MatchTable::LineBreak
;
1093 //===- RecordRegisterType ------------------------------------------===//
1095 void RecordRegisterType::emitPredicateOpcodes(MatchTable
&Table
,
1096 RuleMatcher
&Rule
) const {
1097 assert(Idx
< 0 && "Temp types always have negative indexes!");
1098 Table
<< MatchTable::Opcode("GIM_RecordRegType") << MatchTable::Comment("MI")
1099 << MatchTable::IntValue(InsnVarID
) << MatchTable::Comment("Op")
1100 << MatchTable::IntValue(OpIdx
) << MatchTable::Comment("TempTypeIdx")
1101 << MatchTable::IntValue(Idx
) << MatchTable::LineBreak
;
1104 //===- ComplexPatternOperandMatcher ---------------------------------------===//
1106 void ComplexPatternOperandMatcher::emitPredicateOpcodes(
1107 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1108 unsigned ID
= getAllocatedTemporariesBaseID();
1109 Table
<< MatchTable::Opcode("GIM_CheckComplexPattern")
1110 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1111 << MatchTable::Comment("Op") << MatchTable::IntValue(OpIdx
)
1112 << MatchTable::Comment("Renderer") << MatchTable::IntValue(ID
)
1113 << MatchTable::NamedValue(("GICP_" + TheDef
.getName()).str())
1114 << MatchTable::LineBreak
;
1117 unsigned ComplexPatternOperandMatcher::getAllocatedTemporariesBaseID() const {
1118 return Operand
.getAllocatedTemporariesBaseID();
1121 //===- RegisterBankOperandMatcher -----------------------------------------===//
1123 bool RegisterBankOperandMatcher::isIdentical(const PredicateMatcher
&B
) const {
1124 return OperandPredicateMatcher::isIdentical(B
) &&
1125 RC
.getDef() == cast
<RegisterBankOperandMatcher
>(&B
)->RC
.getDef();
1128 void RegisterBankOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1129 RuleMatcher
&Rule
) const {
1130 Table
<< MatchTable::Opcode("GIM_CheckRegBankForClass")
1131 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1132 << MatchTable::Comment("Op") << MatchTable::IntValue(OpIdx
)
1133 << MatchTable::Comment("RC")
1134 << MatchTable::NamedValue(RC
.getQualifiedIdName())
1135 << MatchTable::LineBreak
;
1138 //===- MBBOperandMatcher --------------------------------------------------===//
1140 void MBBOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1141 RuleMatcher
&Rule
) const {
1142 Table
<< MatchTable::Opcode("GIM_CheckIsMBB") << MatchTable::Comment("MI")
1143 << MatchTable::IntValue(InsnVarID
) << MatchTable::Comment("Op")
1144 << MatchTable::IntValue(OpIdx
) << MatchTable::LineBreak
;
1147 //===- ImmOperandMatcher --------------------------------------------------===//
1149 void ImmOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1150 RuleMatcher
&Rule
) const {
1151 Table
<< MatchTable::Opcode("GIM_CheckIsImm") << MatchTable::Comment("MI")
1152 << MatchTable::IntValue(InsnVarID
) << MatchTable::Comment("Op")
1153 << MatchTable::IntValue(OpIdx
) << MatchTable::LineBreak
;
1156 //===- ConstantIntOperandMatcher ------------------------------------------===//
1158 void ConstantIntOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1159 RuleMatcher
&Rule
) const {
1160 Table
<< MatchTable::Opcode("GIM_CheckConstantInt")
1161 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1162 << MatchTable::Comment("Op") << MatchTable::IntValue(OpIdx
)
1163 << MatchTable::IntValue(Value
) << MatchTable::LineBreak
;
1166 //===- LiteralIntOperandMatcher -------------------------------------------===//
1168 void LiteralIntOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1169 RuleMatcher
&Rule
) const {
1170 Table
<< MatchTable::Opcode("GIM_CheckLiteralInt")
1171 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1172 << MatchTable::Comment("Op") << MatchTable::IntValue(OpIdx
)
1173 << MatchTable::IntValue(Value
) << MatchTable::LineBreak
;
1176 //===- CmpPredicateOperandMatcher -----------------------------------------===//
1178 void CmpPredicateOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1179 RuleMatcher
&Rule
) const {
1180 Table
<< MatchTable::Opcode("GIM_CheckCmpPredicate")
1181 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1182 << MatchTable::Comment("Op") << MatchTable::IntValue(OpIdx
)
1183 << MatchTable::Comment("Predicate")
1184 << MatchTable::NamedValue("CmpInst", PredName
) << MatchTable::LineBreak
;
1187 //===- IntrinsicIDOperandMatcher ------------------------------------------===//
1189 void IntrinsicIDOperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1190 RuleMatcher
&Rule
) const {
1191 Table
<< MatchTable::Opcode("GIM_CheckIntrinsicID")
1192 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1193 << MatchTable::Comment("Op") << MatchTable::IntValue(OpIdx
)
1194 << MatchTable::NamedValue("Intrinsic::" + II
->EnumName
)
1195 << MatchTable::LineBreak
;
1198 //===- OperandImmPredicateMatcher -----------------------------------------===//
1200 void OperandImmPredicateMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1201 RuleMatcher
&Rule
) const {
1202 Table
<< MatchTable::Opcode("GIM_CheckImmOperandPredicate")
1203 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1204 << MatchTable::Comment("MO") << MatchTable::IntValue(OpIdx
)
1205 << MatchTable::Comment("Predicate")
1206 << MatchTable::NamedValue(getEnumNameForPredicate(Predicate
))
1207 << MatchTable::LineBreak
;
1210 //===- OperandMatcher -----------------------------------------------------===//
1212 std::string
OperandMatcher::getOperandExpr(unsigned InsnVarID
) const {
1213 return "State.MIs[" + llvm::to_string(InsnVarID
) + "]->getOperand(" +
1214 llvm::to_string(OpIdx
) + ")";
1217 unsigned OperandMatcher::getInsnVarID() const { return Insn
.getInsnVarID(); }
1219 TempTypeIdx
OperandMatcher::getTempTypeIdx(RuleMatcher
&Rule
) {
1221 // Temp type index not assigned yet, so assign one and add the necessary
1223 TTIdx
= Rule
.getNextTempTypeIdx();
1225 addPredicate
<RecordRegisterType
>(TTIdx
);
1231 void OperandMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1232 RuleMatcher
&Rule
) {
1234 std::string Comment
;
1235 raw_string_ostream
CommentOS(Comment
);
1236 CommentOS
<< "MIs[" << getInsnVarID() << "] ";
1237 if (SymbolicName
.empty())
1238 CommentOS
<< "Operand " << OpIdx
;
1240 CommentOS
<< SymbolicName
;
1241 Table
<< MatchTable::Comment(Comment
) << MatchTable::LineBreak
;
1244 emitPredicateListOpcodes(Table
, Rule
);
1247 bool OperandMatcher::isHigherPriorityThan(OperandMatcher
&B
) {
1248 // Operand matchers involving more predicates have higher priority.
1249 if (predicates_size() > B
.predicates_size())
1251 if (predicates_size() < B
.predicates_size())
1254 // This assumes that predicates are added in a consistent order.
1255 for (auto &&Predicate
: zip(predicates(), B
.predicates())) {
1256 if (std::get
<0>(Predicate
)->isHigherPriorityThan(*std::get
<1>(Predicate
)))
1258 if (std::get
<1>(Predicate
)->isHigherPriorityThan(*std::get
<0>(Predicate
)))
1265 unsigned OperandMatcher::countRendererFns() {
1266 return std::accumulate(
1267 predicates().begin(), predicates().end(), 0,
1269 const std::unique_ptr
<OperandPredicateMatcher
> &Predicate
) {
1270 return A
+ Predicate
->countRendererFns();
1274 Error
OperandMatcher::addTypeCheckPredicate(const TypeSetByHwMode
&VTy
,
1275 bool OperandIsAPointer
) {
1276 if (!VTy
.isMachineValueType())
1277 return failUnsupported("unsupported typeset");
1279 if (VTy
.getMachineValueType() == MVT::iPTR
&& OperandIsAPointer
) {
1280 addPredicate
<PointerToAnyOperandMatcher
>(0);
1281 return Error::success();
1284 auto OpTyOrNone
= MVTToLLT(VTy
.getMachineValueType().SimpleTy
);
1286 return failUnsupported("unsupported type");
1288 if (OperandIsAPointer
)
1289 addPredicate
<PointerToAnyOperandMatcher
>(OpTyOrNone
->get().getSizeInBits());
1290 else if (VTy
.isPointer())
1291 addPredicate
<LLTOperandMatcher
>(
1292 LLT::pointer(VTy
.getPtrAddrSpace(), OpTyOrNone
->get().getSizeInBits()));
1294 addPredicate
<LLTOperandMatcher
>(*OpTyOrNone
);
1295 return Error::success();
1298 //===- InstructionOpcodeMatcher -------------------------------------------===//
1300 DenseMap
<const CodeGenInstruction
*, unsigned>
1301 InstructionOpcodeMatcher::OpcodeValues
;
1304 InstructionOpcodeMatcher::getInstValue(const CodeGenInstruction
*I
) const {
1305 const auto VI
= OpcodeValues
.find(I
);
1306 if (VI
!= OpcodeValues
.end())
1307 return MatchTable::NamedValue(I
->Namespace
, I
->TheDef
->getName(),
1309 return MatchTable::NamedValue(I
->Namespace
, I
->TheDef
->getName());
1312 void InstructionOpcodeMatcher::initOpcodeValuesMap(
1313 const CodeGenTarget
&Target
) {
1314 OpcodeValues
.clear();
1316 unsigned OpcodeValue
= 0;
1317 for (const CodeGenInstruction
*I
: Target
.getInstructionsByEnumValue())
1318 OpcodeValues
[I
] = OpcodeValue
++;
1321 MatchTableRecord
InstructionOpcodeMatcher::getValue() const {
1322 assert(Insts
.size() == 1);
1324 const CodeGenInstruction
*I
= Insts
[0];
1325 const auto VI
= OpcodeValues
.find(I
);
1326 if (VI
!= OpcodeValues
.end())
1327 return MatchTable::NamedValue(I
->Namespace
, I
->TheDef
->getName(),
1329 return MatchTable::NamedValue(I
->Namespace
, I
->TheDef
->getName());
1332 void InstructionOpcodeMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1333 RuleMatcher
&Rule
) const {
1334 StringRef CheckType
=
1335 Insts
.size() == 1 ? "GIM_CheckOpcode" : "GIM_CheckOpcodeIsEither";
1336 Table
<< MatchTable::Opcode(CheckType
) << MatchTable::Comment("MI")
1337 << MatchTable::IntValue(InsnVarID
);
1339 for (const CodeGenInstruction
*I
: Insts
)
1340 Table
<< getInstValue(I
);
1341 Table
<< MatchTable::LineBreak
;
1344 bool InstructionOpcodeMatcher::isHigherPriorityThan(
1345 const InstructionPredicateMatcher
&B
) const {
1346 if (InstructionPredicateMatcher::isHigherPriorityThan(B
))
1348 if (B
.InstructionPredicateMatcher::isHigherPriorityThan(*this))
1351 // Prioritize opcodes for cosmetic reasons in the generated source. Although
1352 // this is cosmetic at the moment, we may want to drive a similar ordering
1353 // using instruction frequency information to improve compile time.
1354 if (const InstructionOpcodeMatcher
*BO
=
1355 dyn_cast
<InstructionOpcodeMatcher
>(&B
))
1356 return Insts
[0]->TheDef
->getName() < BO
->Insts
[0]->TheDef
->getName();
1361 bool InstructionOpcodeMatcher::isConstantInstruction() const {
1362 return Insts
.size() == 1 && Insts
[0]->TheDef
->getName() == "G_CONSTANT";
1365 StringRef
InstructionOpcodeMatcher::getOpcode() const {
1366 return Insts
[0]->TheDef
->getName();
1369 bool InstructionOpcodeMatcher::isVariadicNumOperands() const {
1370 // If one is variadic, they all should be.
1371 return Insts
[0]->Operands
.isVariadic
;
1374 StringRef
InstructionOpcodeMatcher::getOperandType(unsigned OpIdx
) const {
1375 // Types expected to be uniform for all alternatives.
1376 return Insts
[0]->Operands
[OpIdx
].OperandType
;
1379 //===- InstructionNumOperandsMatcher --------------------------------------===//
1381 void InstructionNumOperandsMatcher::emitPredicateOpcodes(
1382 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1383 Table
<< MatchTable::Opcode("GIM_CheckNumOperands")
1384 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1385 << MatchTable::Comment("Expected") << MatchTable::IntValue(NumOperands
)
1386 << MatchTable::LineBreak
;
1389 //===- InstructionImmPredicateMatcher -------------------------------------===//
1391 bool InstructionImmPredicateMatcher::isIdentical(
1392 const PredicateMatcher
&B
) const {
1393 return InstructionPredicateMatcher::isIdentical(B
) &&
1394 Predicate
.getOrigPatFragRecord() ==
1395 cast
<InstructionImmPredicateMatcher
>(&B
)
1396 ->Predicate
.getOrigPatFragRecord();
1399 void InstructionImmPredicateMatcher::emitPredicateOpcodes(
1400 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1401 Table
<< MatchTable::Opcode(getMatchOpcodeForImmPredicate(Predicate
))
1402 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1403 << MatchTable::Comment("Predicate")
1404 << MatchTable::NamedValue(getEnumNameForPredicate(Predicate
))
1405 << MatchTable::LineBreak
;
1408 //===- AtomicOrderingMMOPredicateMatcher ----------------------------------===//
1410 bool AtomicOrderingMMOPredicateMatcher::isIdentical(
1411 const PredicateMatcher
&B
) const {
1412 if (!InstructionPredicateMatcher::isIdentical(B
))
1414 const auto &R
= *cast
<AtomicOrderingMMOPredicateMatcher
>(&B
);
1415 return Order
== R
.Order
&& Comparator
== R
.Comparator
;
1418 void AtomicOrderingMMOPredicateMatcher::emitPredicateOpcodes(
1419 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1420 StringRef Opcode
= "GIM_CheckAtomicOrdering";
1422 if (Comparator
== AO_OrStronger
)
1423 Opcode
= "GIM_CheckAtomicOrderingOrStrongerThan";
1424 if (Comparator
== AO_WeakerThan
)
1425 Opcode
= "GIM_CheckAtomicOrderingWeakerThan";
1427 Table
<< MatchTable::Opcode(Opcode
) << MatchTable::Comment("MI")
1428 << MatchTable::IntValue(InsnVarID
) << MatchTable::Comment("Order")
1429 << MatchTable::NamedValue(("(int64_t)AtomicOrdering::" + Order
).str())
1430 << MatchTable::LineBreak
;
1433 //===- MemorySizePredicateMatcher -----------------------------------------===//
1435 void MemorySizePredicateMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1436 RuleMatcher
&Rule
) const {
1437 Table
<< MatchTable::Opcode("GIM_CheckMemorySizeEqualTo")
1438 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1439 << MatchTable::Comment("MMO") << MatchTable::IntValue(MMOIdx
)
1440 << MatchTable::Comment("Size") << MatchTable::IntValue(Size
)
1441 << MatchTable::LineBreak
;
1444 //===- MemoryAddressSpacePredicateMatcher ---------------------------------===//
1446 bool MemoryAddressSpacePredicateMatcher::isIdentical(
1447 const PredicateMatcher
&B
) const {
1448 if (!InstructionPredicateMatcher::isIdentical(B
))
1450 auto *Other
= cast
<MemoryAddressSpacePredicateMatcher
>(&B
);
1451 return MMOIdx
== Other
->MMOIdx
&& AddrSpaces
== Other
->AddrSpaces
;
1454 void MemoryAddressSpacePredicateMatcher::emitPredicateOpcodes(
1455 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1456 Table
<< MatchTable::Opcode("GIM_CheckMemoryAddressSpace")
1457 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1458 << MatchTable::Comment("MMO")
1459 << MatchTable::IntValue(MMOIdx
)
1460 // Encode number of address spaces to expect.
1461 << MatchTable::Comment("NumAddrSpace")
1462 << MatchTable::IntValue(AddrSpaces
.size());
1463 for (unsigned AS
: AddrSpaces
)
1464 Table
<< MatchTable::Comment("AddrSpace") << MatchTable::IntValue(AS
);
1466 Table
<< MatchTable::LineBreak
;
1469 //===- MemoryAlignmentPredicateMatcher ------------------------------------===//
1471 bool MemoryAlignmentPredicateMatcher::isIdentical(
1472 const PredicateMatcher
&B
) const {
1473 if (!InstructionPredicateMatcher::isIdentical(B
))
1475 auto *Other
= cast
<MemoryAlignmentPredicateMatcher
>(&B
);
1476 return MMOIdx
== Other
->MMOIdx
&& MinAlign
== Other
->MinAlign
;
1479 void MemoryAlignmentPredicateMatcher::emitPredicateOpcodes(
1480 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1481 Table
<< MatchTable::Opcode("GIM_CheckMemoryAlignment")
1482 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1483 << MatchTable::Comment("MMO") << MatchTable::IntValue(MMOIdx
)
1484 << MatchTable::Comment("MinAlign") << MatchTable::IntValue(MinAlign
)
1485 << MatchTable::LineBreak
;
1488 //===- MemoryVsLLTSizePredicateMatcher ------------------------------------===//
1490 bool MemoryVsLLTSizePredicateMatcher::isIdentical(
1491 const PredicateMatcher
&B
) const {
1492 return InstructionPredicateMatcher::isIdentical(B
) &&
1493 MMOIdx
== cast
<MemoryVsLLTSizePredicateMatcher
>(&B
)->MMOIdx
&&
1494 Relation
== cast
<MemoryVsLLTSizePredicateMatcher
>(&B
)->Relation
&&
1495 OpIdx
== cast
<MemoryVsLLTSizePredicateMatcher
>(&B
)->OpIdx
;
1498 void MemoryVsLLTSizePredicateMatcher::emitPredicateOpcodes(
1499 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1500 Table
<< MatchTable::Opcode(
1501 Relation
== EqualTo
? "GIM_CheckMemorySizeEqualToLLT"
1502 : Relation
== GreaterThan
? "GIM_CheckMemorySizeGreaterThanLLT"
1503 : "GIM_CheckMemorySizeLessThanLLT")
1504 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1505 << MatchTable::Comment("MMO") << MatchTable::IntValue(MMOIdx
)
1506 << MatchTable::Comment("OpIdx") << MatchTable::IntValue(OpIdx
)
1507 << MatchTable::LineBreak
;
1510 //===- VectorSplatImmPredicateMatcher -------------------------------------===//
1512 void VectorSplatImmPredicateMatcher::emitPredicateOpcodes(
1513 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1514 if (Kind
== AllOnes
)
1515 Table
<< MatchTable::Opcode("GIM_CheckIsBuildVectorAllOnes");
1517 Table
<< MatchTable::Opcode("GIM_CheckIsBuildVectorAllZeros");
1519 Table
<< MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
);
1520 Table
<< MatchTable::LineBreak
;
1523 //===- GenericInstructionPredicateMatcher ---------------------------------===//
1525 GenericInstructionPredicateMatcher::GenericInstructionPredicateMatcher(
1526 unsigned InsnVarID
, TreePredicateFn Predicate
)
1527 : GenericInstructionPredicateMatcher(InsnVarID
,
1528 getEnumNameForPredicate(Predicate
)) {}
1530 bool GenericInstructionPredicateMatcher::isIdentical(
1531 const PredicateMatcher
&B
) const {
1532 return InstructionPredicateMatcher::isIdentical(B
) &&
1534 static_cast<const GenericInstructionPredicateMatcher
&>(B
).EnumVal
;
1536 void GenericInstructionPredicateMatcher::emitPredicateOpcodes(
1537 MatchTable
&Table
, RuleMatcher
&Rule
) const {
1538 Table
<< MatchTable::Opcode("GIM_CheckCxxInsnPredicate")
1539 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID
)
1540 << MatchTable::Comment("FnId") << MatchTable::NamedValue(EnumVal
)
1541 << MatchTable::LineBreak
;
1544 //===- InstructionMatcher -------------------------------------------------===//
1547 InstructionMatcher::addOperand(unsigned OpIdx
, const std::string
&SymbolicName
,
1548 unsigned AllocatedTemporariesBaseID
) {
1549 Operands
.emplace_back(new OperandMatcher(*this, OpIdx
, SymbolicName
,
1550 AllocatedTemporariesBaseID
));
1551 if (!SymbolicName
.empty())
1552 Rule
.defineOperand(SymbolicName
, *Operands
.back());
1554 return *Operands
.back();
1557 OperandMatcher
&InstructionMatcher::getOperand(unsigned OpIdx
) {
1558 auto I
= llvm::find_if(Operands
,
1559 [&OpIdx
](const std::unique_ptr
<OperandMatcher
> &X
) {
1560 return X
->getOpIdx() == OpIdx
;
1562 if (I
!= Operands
.end())
1564 llvm_unreachable("Failed to lookup operand");
1567 OperandMatcher
&InstructionMatcher::addPhysRegInput(Record
*Reg
, unsigned OpIdx
,
1568 unsigned TempOpIdx
) {
1569 assert(SymbolicName
.empty());
1570 OperandMatcher
*OM
= new OperandMatcher(*this, OpIdx
, "", TempOpIdx
);
1571 Operands
.emplace_back(OM
);
1572 Rule
.definePhysRegOperand(Reg
, *OM
);
1573 PhysRegInputs
.emplace_back(Reg
, OpIdx
);
1577 void InstructionMatcher::emitPredicateOpcodes(MatchTable
&Table
,
1578 RuleMatcher
&Rule
) {
1579 if (NumOperandsCheck
)
1580 InstructionNumOperandsMatcher(InsnVarID
, getNumOperands())
1581 .emitPredicateOpcodes(Table
, Rule
);
1583 // First emit all instruction level predicates need to be verified before we
1584 // can verify operands.
1585 emitFilteredPredicateListOpcodes(
1586 [](const PredicateMatcher
&P
) { return !P
.dependsOnOperands(); }, Table
,
1589 // Emit all operand constraints.
1590 for (const auto &Operand
: Operands
)
1591 Operand
->emitPredicateOpcodes(Table
, Rule
);
1593 // All of the tablegen defined predicates should now be matched. Now emit
1594 // any custom predicates that rely on all generated checks.
1595 emitFilteredPredicateListOpcodes(
1596 [](const PredicateMatcher
&P
) { return P
.dependsOnOperands(); }, Table
,
1600 bool InstructionMatcher::isHigherPriorityThan(InstructionMatcher
&B
) {
1601 // Instruction matchers involving more operands have higher priority.
1602 if (Operands
.size() > B
.Operands
.size())
1604 if (Operands
.size() < B
.Operands
.size())
1607 for (auto &&P
: zip(predicates(), B
.predicates())) {
1608 auto L
= static_cast<InstructionPredicateMatcher
*>(std::get
<0>(P
).get());
1609 auto R
= static_cast<InstructionPredicateMatcher
*>(std::get
<1>(P
).get());
1610 if (L
->isHigherPriorityThan(*R
))
1612 if (R
->isHigherPriorityThan(*L
))
1616 for (auto Operand
: zip(Operands
, B
.Operands
)) {
1617 if (std::get
<0>(Operand
)->isHigherPriorityThan(*std::get
<1>(Operand
)))
1619 if (std::get
<1>(Operand
)->isHigherPriorityThan(*std::get
<0>(Operand
)))
1626 unsigned InstructionMatcher::countRendererFns() {
1627 return std::accumulate(
1628 predicates().begin(), predicates().end(), 0,
1630 const std::unique_ptr
<PredicateMatcher
> &Predicate
) {
1631 return A
+ Predicate
->countRendererFns();
1634 Operands
.begin(), Operands
.end(), 0,
1635 [](unsigned A
, const std::unique_ptr
<OperandMatcher
> &Operand
) {
1636 return A
+ Operand
->countRendererFns();
1640 void InstructionMatcher::optimize() {
1641 SmallVector
<std::unique_ptr
<PredicateMatcher
>, 8> Stash
;
1642 const auto &OpcMatcher
= getOpcodeMatcher();
1644 Stash
.push_back(predicates_pop_front());
1645 if (Stash
.back().get() == &OpcMatcher
) {
1646 if (NumOperandsCheck
&& OpcMatcher
.isVariadicNumOperands() &&
1647 getNumOperands() != 0)
1649 new InstructionNumOperandsMatcher(InsnVarID
, getNumOperands()));
1650 NumOperandsCheck
= false;
1652 for (auto &OM
: Operands
)
1653 for (auto &OP
: OM
->predicates())
1654 if (isa
<IntrinsicIDOperandMatcher
>(OP
)) {
1655 Stash
.push_back(std::move(OP
));
1656 OM
->eraseNullPredicates();
1661 if (InsnVarID
> 0) {
1662 assert(!Operands
.empty() && "Nested instruction is expected to def a vreg");
1663 for (auto &OP
: Operands
[0]->predicates())
1665 Operands
[0]->eraseNullPredicates();
1667 for (auto &OM
: Operands
) {
1668 for (auto &OP
: OM
->predicates())
1669 if (isa
<LLTOperandMatcher
>(OP
))
1670 Stash
.push_back(std::move(OP
));
1671 OM
->eraseNullPredicates();
1673 while (!Stash
.empty())
1674 prependPredicate(Stash
.pop_back_val());
1677 //===- InstructionOperandMatcher ------------------------------------------===//
1679 void InstructionOperandMatcher::emitCaptureOpcodes(MatchTable
&Table
,
1680 RuleMatcher
&Rule
) const {
1681 const unsigned NewInsnVarID
= InsnMatcher
->getInsnVarID();
1682 const bool IgnoreCopies
= Flags
& GISF_IgnoreCopies
;
1683 Table
<< MatchTable::Opcode(IgnoreCopies
? "GIM_RecordInsnIgnoreCopies"
1685 << MatchTable::Comment("DefineMI") << MatchTable::IntValue(NewInsnVarID
)
1686 << MatchTable::Comment("MI") << MatchTable::IntValue(getInsnVarID())
1687 << MatchTable::Comment("OpIdx") << MatchTable::IntValue(getOpIdx())
1688 << MatchTable::Comment("MIs[" + llvm::to_string(NewInsnVarID
) + "]")
1689 << MatchTable::LineBreak
;
1692 bool InstructionOperandMatcher::isHigherPriorityThan(
1693 const OperandPredicateMatcher
&B
) const {
1694 if (OperandPredicateMatcher::isHigherPriorityThan(B
))
1696 if (B
.OperandPredicateMatcher::isHigherPriorityThan(*this))
1699 if (const InstructionOperandMatcher
*BP
=
1700 dyn_cast
<InstructionOperandMatcher
>(&B
))
1701 if (InsnMatcher
->isHigherPriorityThan(*BP
->InsnMatcher
))
1706 //===- OperandRenderer ----------------------------------------------------===//
1708 OperandRenderer::~OperandRenderer() {}
1710 //===- CopyRenderer -------------------------------------------------------===//
1712 void CopyRenderer::emitRenderOpcodes(MatchTable
&Table
,
1713 RuleMatcher
&Rule
) const {
1714 const OperandMatcher
&Operand
= Rule
.getOperandMatcher(SymbolicName
);
1715 unsigned OldInsnVarID
= Rule
.getInsnVarID(Operand
.getInstructionMatcher());
1716 Table
<< MatchTable::Opcode("GIR_Copy") << MatchTable::Comment("NewInsnID")
1717 << MatchTable::IntValue(NewInsnID
) << MatchTable::Comment("OldInsnID")
1718 << MatchTable::IntValue(OldInsnVarID
) << MatchTable::Comment("OpIdx")
1719 << MatchTable::IntValue(Operand
.getOpIdx())
1720 << MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
1723 //===- CopyPhysRegRenderer ------------------------------------------------===//
1725 void CopyPhysRegRenderer::emitRenderOpcodes(MatchTable
&Table
,
1726 RuleMatcher
&Rule
) const {
1727 const OperandMatcher
&Operand
= Rule
.getPhysRegOperandMatcher(PhysReg
);
1728 unsigned OldInsnVarID
= Rule
.getInsnVarID(Operand
.getInstructionMatcher());
1729 Table
<< MatchTable::Opcode("GIR_Copy") << MatchTable::Comment("NewInsnID")
1730 << MatchTable::IntValue(NewInsnID
) << MatchTable::Comment("OldInsnID")
1731 << MatchTable::IntValue(OldInsnVarID
) << MatchTable::Comment("OpIdx")
1732 << MatchTable::IntValue(Operand
.getOpIdx())
1733 << MatchTable::Comment(PhysReg
->getName()) << MatchTable::LineBreak
;
1736 //===- CopyOrAddZeroRegRenderer -------------------------------------------===//
1738 void CopyOrAddZeroRegRenderer::emitRenderOpcodes(MatchTable
&Table
,
1739 RuleMatcher
&Rule
) const {
1740 const OperandMatcher
&Operand
= Rule
.getOperandMatcher(SymbolicName
);
1741 unsigned OldInsnVarID
= Rule
.getInsnVarID(Operand
.getInstructionMatcher());
1742 Table
<< MatchTable::Opcode("GIR_CopyOrAddZeroReg")
1743 << MatchTable::Comment("NewInsnID") << MatchTable::IntValue(NewInsnID
)
1744 << MatchTable::Comment("OldInsnID")
1745 << MatchTable::IntValue(OldInsnVarID
) << MatchTable::Comment("OpIdx")
1746 << MatchTable::IntValue(Operand
.getOpIdx())
1747 << MatchTable::NamedValue(
1748 (ZeroRegisterDef
->getValue("Namespace")
1749 ? ZeroRegisterDef
->getValueAsString("Namespace")
1751 ZeroRegisterDef
->getName())
1752 << MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
1755 //===- CopyConstantAsImmRenderer ------------------------------------------===//
1757 void CopyConstantAsImmRenderer::emitRenderOpcodes(MatchTable
&Table
,
1758 RuleMatcher
&Rule
) const {
1759 InstructionMatcher
&InsnMatcher
= Rule
.getInstructionMatcher(SymbolicName
);
1760 unsigned OldInsnVarID
= Rule
.getInsnVarID(InsnMatcher
);
1761 Table
<< MatchTable::Opcode(Signed
? "GIR_CopyConstantAsSImm"
1762 : "GIR_CopyConstantAsUImm")
1763 << MatchTable::Comment("NewInsnID") << MatchTable::IntValue(NewInsnID
)
1764 << MatchTable::Comment("OldInsnID")
1765 << MatchTable::IntValue(OldInsnVarID
)
1766 << MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
1769 //===- CopyFConstantAsFPImmRenderer ---------------------------------------===//
1771 void CopyFConstantAsFPImmRenderer::emitRenderOpcodes(MatchTable
&Table
,
1772 RuleMatcher
&Rule
) const {
1773 InstructionMatcher
&InsnMatcher
= Rule
.getInstructionMatcher(SymbolicName
);
1774 unsigned OldInsnVarID
= Rule
.getInsnVarID(InsnMatcher
);
1775 Table
<< MatchTable::Opcode("GIR_CopyFConstantAsFPImm")
1776 << MatchTable::Comment("NewInsnID") << MatchTable::IntValue(NewInsnID
)
1777 << MatchTable::Comment("OldInsnID")
1778 << MatchTable::IntValue(OldInsnVarID
)
1779 << MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
1782 //===- CopySubRegRenderer -------------------------------------------------===//
1784 void CopySubRegRenderer::emitRenderOpcodes(MatchTable
&Table
,
1785 RuleMatcher
&Rule
) const {
1786 const OperandMatcher
&Operand
= Rule
.getOperandMatcher(SymbolicName
);
1787 unsigned OldInsnVarID
= Rule
.getInsnVarID(Operand
.getInstructionMatcher());
1788 Table
<< MatchTable::Opcode("GIR_CopySubReg")
1789 << MatchTable::Comment("NewInsnID") << MatchTable::IntValue(NewInsnID
)
1790 << MatchTable::Comment("OldInsnID")
1791 << MatchTable::IntValue(OldInsnVarID
) << MatchTable::Comment("OpIdx")
1792 << MatchTable::IntValue(Operand
.getOpIdx())
1793 << MatchTable::Comment("SubRegIdx")
1794 << MatchTable::IntValue(SubReg
->EnumValue
)
1795 << MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
1798 //===- AddRegisterRenderer ------------------------------------------------===//
1800 void AddRegisterRenderer::emitRenderOpcodes(MatchTable
&Table
,
1801 RuleMatcher
&Rule
) const {
1802 Table
<< MatchTable::Opcode("GIR_AddRegister")
1803 << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID
);
1804 if (RegisterDef
->getName() != "zero_reg") {
1805 Table
<< MatchTable::NamedValue(
1806 (RegisterDef
->getValue("Namespace")
1807 ? RegisterDef
->getValueAsString("Namespace")
1809 RegisterDef
->getName());
1811 Table
<< MatchTable::NamedValue(Target
.getRegNamespace(), "NoRegister");
1813 Table
<< MatchTable::Comment("AddRegisterRegFlags");
1815 // TODO: This is encoded as a 64-bit element, but only 16 or 32-bits are
1816 // really needed for a physical register reference. We can pack the
1817 // register and flags in a single field.
1819 Table
<< MatchTable::NamedValue("RegState::Define");
1821 Table
<< MatchTable::IntValue(0);
1822 Table
<< MatchTable::LineBreak
;
1825 //===- TempRegRenderer ----------------------------------------------------===//
1827 void TempRegRenderer::emitRenderOpcodes(MatchTable
&Table
,
1828 RuleMatcher
&Rule
) const {
1831 Table
<< MatchTable::Opcode("GIR_AddTempSubRegister");
1833 Table
<< MatchTable::Opcode("GIR_AddTempRegister");
1835 Table
<< MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID
)
1836 << MatchTable::Comment("TempRegID") << MatchTable::IntValue(TempRegID
)
1837 << MatchTable::Comment("TempRegFlags");
1840 SmallString
<32> RegFlags
;
1841 RegFlags
+= "RegState::Define";
1843 RegFlags
+= "|RegState::Dead";
1844 Table
<< MatchTable::NamedValue(RegFlags
);
1846 Table
<< MatchTable::IntValue(0);
1849 Table
<< MatchTable::NamedValue(SubRegIdx
->getQualifiedName());
1850 Table
<< MatchTable::LineBreak
;
1853 //===- SubRegIndexRenderer ------------------------------------------------===//
1855 void SubRegIndexRenderer::emitRenderOpcodes(MatchTable
&Table
,
1856 RuleMatcher
&Rule
) const {
1857 Table
<< MatchTable::Opcode("GIR_AddImm") << MatchTable::Comment("InsnID")
1858 << MatchTable::IntValue(InsnID
) << MatchTable::Comment("SubRegIndex")
1859 << MatchTable::IntValue(SubRegIdx
->EnumValue
) << MatchTable::LineBreak
;
1862 //===- RenderComplexPatternOperand ----------------------------------------===//
1864 void RenderComplexPatternOperand::emitRenderOpcodes(MatchTable
&Table
,
1865 RuleMatcher
&Rule
) const {
1866 Table
<< MatchTable::Opcode(
1867 SubOperand
? (SubReg
? "GIR_ComplexSubOperandSubRegRenderer"
1868 : "GIR_ComplexSubOperandRenderer")
1869 : "GIR_ComplexRenderer")
1870 << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID
)
1871 << MatchTable::Comment("RendererID")
1872 << MatchTable::IntValue(RendererID
);
1874 Table
<< MatchTable::Comment("SubOperand")
1875 << MatchTable::IntValue(*SubOperand
);
1877 Table
<< MatchTable::Comment("SubRegIdx")
1878 << MatchTable::IntValue(SubReg
->EnumValue
);
1879 Table
<< MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
1882 //===- CustomRenderer -----------------------------------------------------===//
1884 void CustomRenderer::emitRenderOpcodes(MatchTable
&Table
,
1885 RuleMatcher
&Rule
) const {
1886 InstructionMatcher
&InsnMatcher
= Rule
.getInstructionMatcher(SymbolicName
);
1887 unsigned OldInsnVarID
= Rule
.getInsnVarID(InsnMatcher
);
1888 Table
<< MatchTable::Opcode("GIR_CustomRenderer")
1889 << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID
)
1890 << MatchTable::Comment("OldInsnID")
1891 << MatchTable::IntValue(OldInsnVarID
) << MatchTable::Comment("Renderer")
1892 << MatchTable::NamedValue("GICR_" +
1893 Renderer
.getValueAsString("RendererFn").str())
1894 << MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
1897 //===- CustomOperandRenderer ----------------------------------------------===//
1899 void CustomOperandRenderer::emitRenderOpcodes(MatchTable
&Table
,
1900 RuleMatcher
&Rule
) const {
1901 const OperandMatcher
&OpdMatcher
= Rule
.getOperandMatcher(SymbolicName
);
1902 Table
<< MatchTable::Opcode("GIR_CustomOperandRenderer")
1903 << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID
)
1904 << MatchTable::Comment("OldInsnID")
1905 << MatchTable::IntValue(OpdMatcher
.getInsnVarID())
1906 << MatchTable::Comment("OpIdx")
1907 << MatchTable::IntValue(OpdMatcher
.getOpIdx())
1908 << MatchTable::Comment("OperandRenderer")
1909 << MatchTable::NamedValue("GICR_" +
1910 Renderer
.getValueAsString("RendererFn").str())
1911 << MatchTable::Comment(SymbolicName
) << MatchTable::LineBreak
;
1914 //===- CustomCXXAction ----------------------------------------------------===//
1916 void CustomCXXAction::emitActionOpcodes(MatchTable
&Table
,
1917 RuleMatcher
&Rule
) const {
1918 Table
<< MatchTable::Opcode("GIR_CustomAction")
1919 << MatchTable::NamedValue(FnEnumName
) << MatchTable::LineBreak
;
1922 //===- BuildMIAction ------------------------------------------------------===//
1924 bool BuildMIAction::canMutate(RuleMatcher
&Rule
,
1925 const InstructionMatcher
*Insn
) const {
1929 if (OperandRenderers
.size() != Insn
->getNumOperands())
1932 for (const auto &Renderer
: enumerate(OperandRenderers
)) {
1933 if (const auto *Copy
= dyn_cast
<CopyRenderer
>(&*Renderer
.value())) {
1934 const OperandMatcher
&OM
=
1935 Rule
.getOperandMatcher(Copy
->getSymbolicName());
1936 if (Insn
!= &OM
.getInstructionMatcher() ||
1937 OM
.getOpIdx() != Renderer
.index())
1946 void BuildMIAction::chooseInsnToMutate(RuleMatcher
&Rule
) {
1947 for (auto *MutateCandidate
: Rule
.mutatable_insns()) {
1948 if (canMutate(Rule
, MutateCandidate
)) {
1949 // Take the first one we're offered that we're able to mutate.
1950 Rule
.reserveInsnMatcherForMutation(MutateCandidate
);
1951 Matched
= MutateCandidate
;
1957 void BuildMIAction::emitActionOpcodes(MatchTable
&Table
,
1958 RuleMatcher
&Rule
) const {
1960 assert(canMutate(Rule
, Matched
) &&
1961 "Arranged to mutate an insn that isn't mutatable");
1963 unsigned RecycleInsnID
= Rule
.getInsnVarID(*Matched
);
1964 Table
<< MatchTable::Opcode("GIR_MutateOpcode")
1965 << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID
)
1966 << MatchTable::Comment("RecycleInsnID")
1967 << MatchTable::IntValue(RecycleInsnID
)
1968 << MatchTable::Comment("Opcode")
1969 << MatchTable::NamedValue(I
->Namespace
, I
->TheDef
->getName())
1970 << MatchTable::LineBreak
;
1972 if (!I
->ImplicitDefs
.empty() || !I
->ImplicitUses
.empty()) {
1973 for (auto *Def
: I
->ImplicitDefs
) {
1974 auto Namespace
= Def
->getValue("Namespace")
1975 ? Def
->getValueAsString("Namespace")
1977 const bool IsDead
= DeadImplicitDefs
.contains(Def
);
1978 Table
<< MatchTable::Opcode("GIR_AddImplicitDef")
1979 << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID
)
1980 << MatchTable::NamedValue(Namespace
, Def
->getName())
1981 << (IsDead
? MatchTable::NamedValue("RegState", "Dead")
1982 : MatchTable::IntValue(0))
1983 << MatchTable::LineBreak
;
1985 for (auto *Use
: I
->ImplicitUses
) {
1986 auto Namespace
= Use
->getValue("Namespace")
1987 ? Use
->getValueAsString("Namespace")
1989 Table
<< MatchTable::Opcode("GIR_AddImplicitUse")
1990 << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID
)
1991 << MatchTable::NamedValue(Namespace
, Use
->getName())
1992 << MatchTable::LineBreak
;
1998 // TODO: Simple permutation looks like it could be almost as common as
1999 // mutation due to commutative operations.
2001 Table
<< MatchTable::Opcode("GIR_BuildMI") << MatchTable::Comment("InsnID")
2002 << MatchTable::IntValue(InsnID
) << MatchTable::Comment("Opcode")
2003 << MatchTable::NamedValue(I
->Namespace
, I
->TheDef
->getName())
2004 << MatchTable::LineBreak
;
2005 for (const auto &Renderer
: OperandRenderers
)
2006 Renderer
->emitRenderOpcodes(Table
, Rule
);
2008 for (auto [OpIdx
, Def
] : enumerate(I
->ImplicitDefs
)) {
2010 Def
->getValue("Namespace") ? Def
->getValueAsString("Namespace") : "";
2011 if (DeadImplicitDefs
.contains(Def
)) {
2013 << MatchTable::Opcode("GIR_SetImplicitDefDead")
2014 << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID
)
2015 << MatchTable::Comment(
2016 ("OpIdx for " + Namespace
+ "::" + Def
->getName() + "").str())
2017 << MatchTable::IntValue(OpIdx
) << MatchTable::LineBreak
;
2021 if (I
->mayLoad
|| I
->mayStore
) {
2022 Table
<< MatchTable::Opcode("GIR_MergeMemOperands")
2023 << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID
)
2024 << MatchTable::Comment("MergeInsnID's");
2025 // Emit the ID's for all the instructions that are matched by this rule.
2026 // TODO: Limit this to matched instructions that mayLoad/mayStore or have
2027 // some other means of having a memoperand. Also limit this to
2028 // emitted instructions that expect to have a memoperand too. For
2029 // example, (G_SEXT (G_LOAD x)) that results in separate load and
2030 // sign-extend instructions shouldn't put the memoperand on the
2031 // sign-extend since it has no effect there.
2032 std::vector
<unsigned> MergeInsnIDs
;
2033 for (const auto &IDMatcherPair
: Rule
.defined_insn_vars())
2034 MergeInsnIDs
.push_back(IDMatcherPair
.second
);
2035 llvm::sort(MergeInsnIDs
);
2036 for (const auto &MergeInsnID
: MergeInsnIDs
)
2037 Table
<< MatchTable::IntValue(MergeInsnID
);
2038 Table
<< MatchTable::NamedValue("GIU_MergeMemOperands_EndOfList")
2039 << MatchTable::LineBreak
;
2042 // FIXME: This is a hack but it's sufficient for ISel. We'll need to do
2043 // better for combines. Particularly when there are multiple match
2046 EraseInstAction::emitActionOpcodes(Table
, Rule
, /*InsnID*/ 0);
2049 //===- BuildConstantAction ------------------------------------------------===//
2051 void BuildConstantAction::emitActionOpcodes(MatchTable
&Table
,
2052 RuleMatcher
&Rule
) const {
2053 Table
<< MatchTable::Opcode("GIR_BuildConstant")
2054 << MatchTable::Comment("TempRegID") << MatchTable::IntValue(TempRegID
)
2055 << MatchTable::Comment("Val") << MatchTable::IntValue(Val
)
2056 << MatchTable::LineBreak
;
2059 //===- EraseInstAction ----------------------------------------------------===//
2061 void EraseInstAction::emitActionOpcodes(MatchTable
&Table
, RuleMatcher
&Rule
,
2063 // Avoid erasing the same inst twice.
2064 if (!Rule
.tryEraseInsnID(InsnID
))
2067 Table
<< MatchTable::Opcode("GIR_EraseFromParent")
2068 << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID
)
2069 << MatchTable::LineBreak
;
2072 void EraseInstAction::emitActionOpcodes(MatchTable
&Table
,
2073 RuleMatcher
&Rule
) const {
2074 emitActionOpcodes(Table
, Rule
, InsnID
);
2077 //===- ReplaceRegAction ---------------------------------------------------===//
2079 void ReplaceRegAction::emitAdditionalPredicates(MatchTable
&Table
,
2080 RuleMatcher
&Rule
) const {
2081 if (TempRegID
!= (unsigned)-1)
2084 Table
<< MatchTable::Opcode("GIM_CheckCanReplaceReg")
2085 << MatchTable::Comment("OldInsnID") << MatchTable::IntValue(OldInsnID
)
2086 << MatchTable::Comment("OldOpIdx") << MatchTable::IntValue(OldOpIdx
)
2087 << MatchTable::Comment("NewInsnId") << MatchTable::IntValue(NewInsnId
)
2088 << MatchTable::Comment("NewOpIdx") << MatchTable::IntValue(NewOpIdx
)
2089 << MatchTable::LineBreak
;
2092 void ReplaceRegAction::emitActionOpcodes(MatchTable
&Table
,
2093 RuleMatcher
&Rule
) const {
2094 if (TempRegID
!= (unsigned)-1) {
2095 Table
<< MatchTable::Opcode("GIR_ReplaceRegWithTempReg")
2096 << MatchTable::Comment("OldInsnID") << MatchTable::IntValue(OldInsnID
)
2097 << MatchTable::Comment("OldOpIdx") << MatchTable::IntValue(OldOpIdx
)
2098 << MatchTable::Comment("TempRegID") << MatchTable::IntValue(TempRegID
)
2099 << MatchTable::LineBreak
;
2101 Table
<< MatchTable::Opcode("GIR_ReplaceReg")
2102 << MatchTable::Comment("OldInsnID") << MatchTable::IntValue(OldInsnID
)
2103 << MatchTable::Comment("OldOpIdx") << MatchTable::IntValue(OldOpIdx
)
2104 << MatchTable::Comment("NewInsnId") << MatchTable::IntValue(NewInsnId
)
2105 << MatchTable::Comment("NewOpIdx") << MatchTable::IntValue(NewOpIdx
)
2106 << MatchTable::LineBreak
;
2110 //===- ConstrainOperandToRegClassAction -----------------------------------===//
2112 void ConstrainOperandToRegClassAction::emitActionOpcodes(
2113 MatchTable
&Table
, RuleMatcher
&Rule
) const {
2114 Table
<< MatchTable::Opcode("GIR_ConstrainOperandRC")
2115 << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID
)
2116 << MatchTable::Comment("Op") << MatchTable::IntValue(OpIdx
)
2117 << MatchTable::NamedValue(RC
.getQualifiedIdName())
2118 << MatchTable::LineBreak
;
2121 //===- MakeTempRegisterAction ---------------------------------------------===//
2123 void MakeTempRegisterAction::emitActionOpcodes(MatchTable
&Table
,
2124 RuleMatcher
&Rule
) const {
2125 Table
<< MatchTable::Opcode("GIR_MakeTempReg")
2126 << MatchTable::Comment("TempRegID") << MatchTable::IntValue(TempRegID
)
2127 << MatchTable::Comment("TypeID") << Ty
<< MatchTable::LineBreak
;