xref: /freebsd-src/contrib/llvm-project/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===- GlobalISelMatchTable.cpp -------------------------------------------===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric 
9*0fca6ea1SDimitry Andric #include "GlobalISelMatchTable.h"
10*0fca6ea1SDimitry Andric #include "Common/CodeGenInstruction.h"
11*0fca6ea1SDimitry Andric #include "Common/CodeGenRegisters.h"
12*0fca6ea1SDimitry Andric #include "llvm/ADT/Statistic.h"
13*0fca6ea1SDimitry Andric #include "llvm/Support/Debug.h"
14*0fca6ea1SDimitry Andric #include "llvm/Support/LEB128.h"
15*0fca6ea1SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
16*0fca6ea1SDimitry Andric #include "llvm/Support/raw_ostream.h"
17*0fca6ea1SDimitry Andric #include "llvm/TableGen/Error.h"
18*0fca6ea1SDimitry Andric 
19*0fca6ea1SDimitry Andric #define DEBUG_TYPE "gi-match-table"
20*0fca6ea1SDimitry Andric 
21*0fca6ea1SDimitry Andric STATISTIC(NumPatternEmitted, "Number of patterns emitted");
22*0fca6ea1SDimitry Andric 
23*0fca6ea1SDimitry Andric namespace llvm {
24*0fca6ea1SDimitry Andric namespace gi {
25*0fca6ea1SDimitry Andric 
26*0fca6ea1SDimitry Andric namespace {
27*0fca6ea1SDimitry Andric 
28*0fca6ea1SDimitry Andric Error failUnsupported(const Twine &Reason) {
29*0fca6ea1SDimitry Andric   return make_error<StringError>(Reason, inconvertibleErrorCode());
30*0fca6ea1SDimitry Andric }
31*0fca6ea1SDimitry Andric 
32*0fca6ea1SDimitry Andric /// Get the name of the enum value used to number the predicate function.
33*0fca6ea1SDimitry Andric std::string getEnumNameForPredicate(const TreePredicateFn &Predicate) {
34*0fca6ea1SDimitry Andric   if (Predicate.hasGISelPredicateCode())
35*0fca6ea1SDimitry Andric     return "GICXXPred_MI_" + Predicate.getFnName();
36*0fca6ea1SDimitry Andric   return "GICXXPred_" + Predicate.getImmTypeIdentifier().str() + "_" +
37*0fca6ea1SDimitry Andric          Predicate.getFnName();
38*0fca6ea1SDimitry Andric }
39*0fca6ea1SDimitry Andric 
40*0fca6ea1SDimitry Andric std::string getMatchOpcodeForImmPredicate(const TreePredicateFn &Predicate) {
41*0fca6ea1SDimitry Andric   return "GIM_Check" + Predicate.getImmTypeIdentifier().str() + "ImmPredicate";
42*0fca6ea1SDimitry Andric }
43*0fca6ea1SDimitry Andric 
44*0fca6ea1SDimitry Andric // GIMT_Encode2/4/8
45*0fca6ea1SDimitry Andric constexpr StringLiteral EncodeMacroName = "GIMT_Encode";
46*0fca6ea1SDimitry Andric 
47*0fca6ea1SDimitry Andric } // namespace
48*0fca6ea1SDimitry Andric 
49*0fca6ea1SDimitry Andric //===- Helpers ------------------------------------------------------------===//
50*0fca6ea1SDimitry Andric 
51*0fca6ea1SDimitry Andric void emitEncodingMacrosDef(raw_ostream &OS) {
52*0fca6ea1SDimitry Andric   OS << "#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__\n"
53*0fca6ea1SDimitry Andric      << "#define " << EncodeMacroName << "2(Val)"
54*0fca6ea1SDimitry Andric      << " uint8_t(Val), uint8_t((uint16_t)Val >> 8)\n"
55*0fca6ea1SDimitry Andric      << "#define " << EncodeMacroName << "4(Val)"
56*0fca6ea1SDimitry Andric      << " uint8_t(Val), uint8_t((uint32_t)Val >> 8), "
57*0fca6ea1SDimitry Andric         "uint8_t((uint32_t)Val >> 16), uint8_t((uint32_t)Val >> 24)\n"
58*0fca6ea1SDimitry Andric      << "#define " << EncodeMacroName << "8(Val)"
59*0fca6ea1SDimitry Andric      << " uint8_t(Val), uint8_t((uint64_t)Val >> 8), "
60*0fca6ea1SDimitry Andric         "uint8_t((uint64_t)Val >> 16), uint8_t((uint64_t)Val >> 24),  "
61*0fca6ea1SDimitry Andric         "uint8_t((uint64_t)Val >> 32), uint8_t((uint64_t)Val >> 40), "
62*0fca6ea1SDimitry Andric         "uint8_t((uint64_t)Val >> 48), uint8_t((uint64_t)Val >> 56)\n"
63*0fca6ea1SDimitry Andric      << "#else\n"
64*0fca6ea1SDimitry Andric      << "#define " << EncodeMacroName << "2(Val)"
65*0fca6ea1SDimitry Andric      << " uint8_t((uint16_t)Val >> 8), uint8_t(Val)\n"
66*0fca6ea1SDimitry Andric      << "#define " << EncodeMacroName << "4(Val)"
67*0fca6ea1SDimitry Andric      << " uint8_t((uint32_t)Val >> 24), uint8_t((uint32_t)Val >> 16), "
68*0fca6ea1SDimitry Andric         "uint8_t((uint32_t)Val >> 8), uint8_t(Val)\n"
69*0fca6ea1SDimitry Andric      << "#define " << EncodeMacroName << "8(Val)"
70*0fca6ea1SDimitry Andric      << " uint8_t((uint64_t)Val >> 56), uint8_t((uint64_t)Val >> 48), "
71*0fca6ea1SDimitry Andric         "uint8_t((uint64_t)Val >> 40), uint8_t((uint64_t)Val >> 32),  "
72*0fca6ea1SDimitry Andric         "uint8_t((uint64_t)Val >> 24), uint8_t((uint64_t)Val >> 16), "
73*0fca6ea1SDimitry Andric         "uint8_t((uint64_t)Val >> 8), uint8_t(Val)\n"
74*0fca6ea1SDimitry Andric      << "#endif\n";
75*0fca6ea1SDimitry Andric }
76*0fca6ea1SDimitry Andric 
77*0fca6ea1SDimitry Andric void emitEncodingMacrosUndef(raw_ostream &OS) {
78*0fca6ea1SDimitry Andric   OS << "#undef " << EncodeMacroName << "2\n"
79*0fca6ea1SDimitry Andric      << "#undef " << EncodeMacroName << "4\n"
80*0fca6ea1SDimitry Andric      << "#undef " << EncodeMacroName << "8\n";
81*0fca6ea1SDimitry Andric }
82*0fca6ea1SDimitry Andric 
83*0fca6ea1SDimitry Andric std::string getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset,
84*0fca6ea1SDimitry Andric                                     int HwModeIdx) {
85*0fca6ea1SDimitry Andric   std::string Name = "GIFBS";
86*0fca6ea1SDimitry Andric   for (const auto &Feature : FeatureBitset)
87*0fca6ea1SDimitry Andric     Name += ("_" + Feature->getName()).str();
88*0fca6ea1SDimitry Andric   if (HwModeIdx >= 0)
89*0fca6ea1SDimitry Andric     Name += ("_HwMode" + std::to_string(HwModeIdx));
90*0fca6ea1SDimitry Andric   return Name;
91*0fca6ea1SDimitry Andric }
92*0fca6ea1SDimitry Andric 
93*0fca6ea1SDimitry Andric template <class GroupT>
94*0fca6ea1SDimitry Andric std::vector<Matcher *>
95*0fca6ea1SDimitry Andric optimizeRules(ArrayRef<Matcher *> Rules,
96*0fca6ea1SDimitry Andric               std::vector<std::unique_ptr<Matcher>> &MatcherStorage) {
97*0fca6ea1SDimitry Andric 
98*0fca6ea1SDimitry Andric   std::vector<Matcher *> OptRules;
99*0fca6ea1SDimitry Andric   std::unique_ptr<GroupT> CurrentGroup = std::make_unique<GroupT>();
100*0fca6ea1SDimitry Andric   assert(CurrentGroup->empty() && "Newly created group isn't empty!");
101*0fca6ea1SDimitry Andric   unsigned NumGroups = 0;
102*0fca6ea1SDimitry Andric 
103*0fca6ea1SDimitry Andric   auto ProcessCurrentGroup = [&]() {
104*0fca6ea1SDimitry Andric     if (CurrentGroup->empty())
105*0fca6ea1SDimitry Andric       // An empty group is good to be reused:
106*0fca6ea1SDimitry Andric       return;
107*0fca6ea1SDimitry Andric 
108*0fca6ea1SDimitry Andric     // If the group isn't large enough to provide any benefit, move all the
109*0fca6ea1SDimitry Andric     // added rules out of it and make sure to re-create the group to properly
110*0fca6ea1SDimitry Andric     // re-initialize it:
111*0fca6ea1SDimitry Andric     if (CurrentGroup->size() < 2)
112*0fca6ea1SDimitry Andric       append_range(OptRules, CurrentGroup->matchers());
113*0fca6ea1SDimitry Andric     else {
114*0fca6ea1SDimitry Andric       CurrentGroup->finalize();
115*0fca6ea1SDimitry Andric       OptRules.push_back(CurrentGroup.get());
116*0fca6ea1SDimitry Andric       MatcherStorage.emplace_back(std::move(CurrentGroup));
117*0fca6ea1SDimitry Andric       ++NumGroups;
118*0fca6ea1SDimitry Andric     }
119*0fca6ea1SDimitry Andric     CurrentGroup = std::make_unique<GroupT>();
120*0fca6ea1SDimitry Andric   };
121*0fca6ea1SDimitry Andric   for (Matcher *Rule : Rules) {
122*0fca6ea1SDimitry Andric     // Greedily add as many matchers as possible to the current group:
123*0fca6ea1SDimitry Andric     if (CurrentGroup->addMatcher(*Rule))
124*0fca6ea1SDimitry Andric       continue;
125*0fca6ea1SDimitry Andric 
126*0fca6ea1SDimitry Andric     ProcessCurrentGroup();
127*0fca6ea1SDimitry Andric     assert(CurrentGroup->empty() && "A group wasn't properly re-initialized");
128*0fca6ea1SDimitry Andric 
129*0fca6ea1SDimitry Andric     // Try to add the pending matcher to a newly created empty group:
130*0fca6ea1SDimitry Andric     if (!CurrentGroup->addMatcher(*Rule))
131*0fca6ea1SDimitry Andric       // If we couldn't add the matcher to an empty group, that group type
132*0fca6ea1SDimitry Andric       // doesn't support that kind of matchers at all, so just skip it:
133*0fca6ea1SDimitry Andric       OptRules.push_back(Rule);
134*0fca6ea1SDimitry Andric   }
135*0fca6ea1SDimitry Andric   ProcessCurrentGroup();
136*0fca6ea1SDimitry Andric 
137*0fca6ea1SDimitry Andric   LLVM_DEBUG(dbgs() << "NumGroups: " << NumGroups << "\n");
138*0fca6ea1SDimitry Andric   (void)NumGroups;
139*0fca6ea1SDimitry Andric   assert(CurrentGroup->empty() && "The last group wasn't properly processed");
140*0fca6ea1SDimitry Andric   return OptRules;
141*0fca6ea1SDimitry Andric }
142*0fca6ea1SDimitry Andric 
143*0fca6ea1SDimitry Andric template std::vector<Matcher *> optimizeRules<GroupMatcher>(
144*0fca6ea1SDimitry Andric     ArrayRef<Matcher *> Rules,
145*0fca6ea1SDimitry Andric     std::vector<std::unique_ptr<Matcher>> &MatcherStorage);
146*0fca6ea1SDimitry Andric 
147*0fca6ea1SDimitry Andric template std::vector<Matcher *> optimizeRules<SwitchMatcher>(
148*0fca6ea1SDimitry Andric     ArrayRef<Matcher *> Rules,
149*0fca6ea1SDimitry Andric     std::vector<std::unique_ptr<Matcher>> &MatcherStorage);
150*0fca6ea1SDimitry Andric 
151*0fca6ea1SDimitry Andric static std::string getEncodedEmitStr(StringRef NamedValue, unsigned NumBytes) {
152*0fca6ea1SDimitry Andric   if (NumBytes == 2 || NumBytes == 4 || NumBytes == 8)
153*0fca6ea1SDimitry Andric     return (EncodeMacroName + Twine(NumBytes) + "(" + NamedValue + ")").str();
154*0fca6ea1SDimitry Andric   llvm_unreachable("Unsupported number of bytes!");
155*0fca6ea1SDimitry Andric }
156*0fca6ea1SDimitry Andric 
157*0fca6ea1SDimitry Andric //===- Global Data --------------------------------------------------------===//
158*0fca6ea1SDimitry Andric 
159*0fca6ea1SDimitry Andric std::set<LLTCodeGen> KnownTypes;
160*0fca6ea1SDimitry Andric 
161*0fca6ea1SDimitry Andric //===- MatchTableRecord ---------------------------------------------------===//
162*0fca6ea1SDimitry Andric 
163*0fca6ea1SDimitry Andric void MatchTableRecord::emit(raw_ostream &OS, bool LineBreakIsNextAfterThis,
164*0fca6ea1SDimitry Andric                             const MatchTable &Table) const {
165*0fca6ea1SDimitry Andric   bool UseLineComment =
166*0fca6ea1SDimitry Andric       LineBreakIsNextAfterThis || (Flags & MTRF_LineBreakFollows);
167*0fca6ea1SDimitry Andric   if (Flags & (MTRF_JumpTarget | MTRF_CommaFollows))
168*0fca6ea1SDimitry Andric     UseLineComment = false;
169*0fca6ea1SDimitry Andric 
170*0fca6ea1SDimitry Andric   if (Flags & MTRF_Comment)
171*0fca6ea1SDimitry Andric     OS << (UseLineComment ? "// " : "/*");
172*0fca6ea1SDimitry Andric 
173*0fca6ea1SDimitry Andric   if (NumElements > 1 && !(Flags & (MTRF_PreEncoded | MTRF_Comment)))
174*0fca6ea1SDimitry Andric     OS << getEncodedEmitStr(EmitStr, NumElements);
175*0fca6ea1SDimitry Andric   else
176*0fca6ea1SDimitry Andric     OS << EmitStr;
177*0fca6ea1SDimitry Andric 
178*0fca6ea1SDimitry Andric   if (Flags & MTRF_Label)
179*0fca6ea1SDimitry Andric     OS << ": @" << Table.getLabelIndex(LabelID);
180*0fca6ea1SDimitry Andric 
181*0fca6ea1SDimitry Andric   if ((Flags & MTRF_Comment) && !UseLineComment)
182*0fca6ea1SDimitry Andric     OS << "*/";
183*0fca6ea1SDimitry Andric 
184*0fca6ea1SDimitry Andric   if (Flags & MTRF_JumpTarget) {
185*0fca6ea1SDimitry Andric     if (Flags & MTRF_Comment)
186*0fca6ea1SDimitry Andric       OS << " ";
187*0fca6ea1SDimitry Andric     // TODO: Could encode this AOT to speed up build of generated file
188*0fca6ea1SDimitry Andric     OS << getEncodedEmitStr(llvm::to_string(Table.getLabelIndex(LabelID)),
189*0fca6ea1SDimitry Andric                             NumElements);
190*0fca6ea1SDimitry Andric   }
191*0fca6ea1SDimitry Andric 
192*0fca6ea1SDimitry Andric   if (Flags & MTRF_CommaFollows) {
193*0fca6ea1SDimitry Andric     OS << ",";
194*0fca6ea1SDimitry Andric     if (!LineBreakIsNextAfterThis && !(Flags & MTRF_LineBreakFollows))
195*0fca6ea1SDimitry Andric       OS << " ";
196*0fca6ea1SDimitry Andric   }
197*0fca6ea1SDimitry Andric 
198*0fca6ea1SDimitry Andric   if (Flags & MTRF_LineBreakFollows)
199*0fca6ea1SDimitry Andric     OS << "\n";
200*0fca6ea1SDimitry Andric }
201*0fca6ea1SDimitry Andric 
202*0fca6ea1SDimitry Andric //===- MatchTable ---------------------------------------------------------===//
203*0fca6ea1SDimitry Andric 
204*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::LineBreak = {
205*0fca6ea1SDimitry Andric     std::nullopt, "" /* Emit String */, 0 /* Elements */,
206*0fca6ea1SDimitry Andric     MatchTableRecord::MTRF_LineBreakFollows};
207*0fca6ea1SDimitry Andric 
208*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::Comment(StringRef Comment) {
209*0fca6ea1SDimitry Andric   return MatchTableRecord(std::nullopt, Comment, 0,
210*0fca6ea1SDimitry Andric                           MatchTableRecord::MTRF_Comment);
211*0fca6ea1SDimitry Andric }
212*0fca6ea1SDimitry Andric 
213*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::Opcode(StringRef Opcode, int IndentAdjust) {
214*0fca6ea1SDimitry Andric   unsigned ExtraFlags = 0;
215*0fca6ea1SDimitry Andric   if (IndentAdjust > 0)
216*0fca6ea1SDimitry Andric     ExtraFlags |= MatchTableRecord::MTRF_Indent;
217*0fca6ea1SDimitry Andric   if (IndentAdjust < 0)
218*0fca6ea1SDimitry Andric     ExtraFlags |= MatchTableRecord::MTRF_Outdent;
219*0fca6ea1SDimitry Andric 
220*0fca6ea1SDimitry Andric   return MatchTableRecord(std::nullopt, Opcode, 1,
221*0fca6ea1SDimitry Andric                           MatchTableRecord::MTRF_CommaFollows | ExtraFlags);
222*0fca6ea1SDimitry Andric }
223*0fca6ea1SDimitry Andric 
224*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::NamedValue(unsigned NumBytes,
225*0fca6ea1SDimitry Andric                                         StringRef NamedValue) {
226*0fca6ea1SDimitry Andric   return MatchTableRecord(std::nullopt, NamedValue, NumBytes,
227*0fca6ea1SDimitry Andric                           MatchTableRecord::MTRF_CommaFollows);
228*0fca6ea1SDimitry Andric }
229*0fca6ea1SDimitry Andric 
230*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::NamedValue(unsigned NumBytes, StringRef NamedValue,
231*0fca6ea1SDimitry Andric                                         int64_t RawValue) {
232*0fca6ea1SDimitry Andric   return MatchTableRecord(std::nullopt, NamedValue, NumBytes,
233*0fca6ea1SDimitry Andric                           MatchTableRecord::MTRF_CommaFollows, RawValue);
234*0fca6ea1SDimitry Andric }
235*0fca6ea1SDimitry Andric 
236*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::NamedValue(unsigned NumBytes, StringRef Namespace,
237*0fca6ea1SDimitry Andric                                         StringRef NamedValue) {
238*0fca6ea1SDimitry Andric   return MatchTableRecord(std::nullopt, (Namespace + "::" + NamedValue).str(),
239*0fca6ea1SDimitry Andric                           NumBytes, MatchTableRecord::MTRF_CommaFollows);
240*0fca6ea1SDimitry Andric }
241*0fca6ea1SDimitry Andric 
242*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::NamedValue(unsigned NumBytes, StringRef Namespace,
243*0fca6ea1SDimitry Andric                                         StringRef NamedValue,
244*0fca6ea1SDimitry Andric                                         int64_t RawValue) {
245*0fca6ea1SDimitry Andric   return MatchTableRecord(std::nullopt, (Namespace + "::" + NamedValue).str(),
246*0fca6ea1SDimitry Andric                           NumBytes, MatchTableRecord::MTRF_CommaFollows,
247*0fca6ea1SDimitry Andric                           RawValue);
248*0fca6ea1SDimitry Andric }
249*0fca6ea1SDimitry Andric 
250*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::IntValue(unsigned NumBytes, int64_t IntValue) {
251*0fca6ea1SDimitry Andric   assert(isUIntN(NumBytes * 8, IntValue) || isIntN(NumBytes * 8, IntValue));
252*0fca6ea1SDimitry Andric   auto Str = llvm::to_string(IntValue);
253*0fca6ea1SDimitry Andric   if (NumBytes == 1 && IntValue < 0)
254*0fca6ea1SDimitry Andric     Str = "uint8_t(" + Str + ")";
255*0fca6ea1SDimitry Andric   // TODO: Could optimize this directly to save the compiler some work when
256*0fca6ea1SDimitry Andric   // building the file
257*0fca6ea1SDimitry Andric   return MatchTableRecord(std::nullopt, Str, NumBytes,
258*0fca6ea1SDimitry Andric                           MatchTableRecord::MTRF_CommaFollows);
259*0fca6ea1SDimitry Andric }
260*0fca6ea1SDimitry Andric 
261*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::ULEB128Value(uint64_t IntValue) {
262*0fca6ea1SDimitry Andric   uint8_t Buffer[10];
263*0fca6ea1SDimitry Andric   unsigned Len = encodeULEB128(IntValue, Buffer);
264*0fca6ea1SDimitry Andric 
265*0fca6ea1SDimitry Andric   // Simple case (most common)
266*0fca6ea1SDimitry Andric   if (Len == 1) {
267*0fca6ea1SDimitry Andric     return MatchTableRecord(std::nullopt, llvm::to_string((unsigned)Buffer[0]),
268*0fca6ea1SDimitry Andric                             1, MatchTableRecord::MTRF_CommaFollows);
269*0fca6ea1SDimitry Andric   }
270*0fca6ea1SDimitry Andric 
271*0fca6ea1SDimitry Andric   // Print it as, e.g. /* -123456 (*/, 0xC0, 0xBB, 0x78 /*)*/
272*0fca6ea1SDimitry Andric   std::string Str;
273*0fca6ea1SDimitry Andric   raw_string_ostream OS(Str);
274*0fca6ea1SDimitry Andric   OS << "/* " << llvm::to_string(IntValue) << "(*/";
275*0fca6ea1SDimitry Andric   for (unsigned K = 0; K < Len; ++K) {
276*0fca6ea1SDimitry Andric     if (K)
277*0fca6ea1SDimitry Andric       OS << ", ";
278*0fca6ea1SDimitry Andric     OS << "0x" << llvm::toHex({Buffer[K]});
279*0fca6ea1SDimitry Andric   }
280*0fca6ea1SDimitry Andric   OS << "/*)*/";
281*0fca6ea1SDimitry Andric   return MatchTableRecord(std::nullopt, Str, Len,
282*0fca6ea1SDimitry Andric                           MatchTableRecord::MTRF_CommaFollows |
283*0fca6ea1SDimitry Andric                               MatchTableRecord::MTRF_PreEncoded);
284*0fca6ea1SDimitry Andric }
285*0fca6ea1SDimitry Andric 
286*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::Label(unsigned LabelID) {
287*0fca6ea1SDimitry Andric   return MatchTableRecord(LabelID, "Label " + llvm::to_string(LabelID), 0,
288*0fca6ea1SDimitry Andric                           MatchTableRecord::MTRF_Label |
289*0fca6ea1SDimitry Andric                               MatchTableRecord::MTRF_Comment |
290*0fca6ea1SDimitry Andric                               MatchTableRecord::MTRF_LineBreakFollows);
291*0fca6ea1SDimitry Andric }
292*0fca6ea1SDimitry Andric 
293*0fca6ea1SDimitry Andric MatchTableRecord MatchTable::JumpTarget(unsigned LabelID) {
294*0fca6ea1SDimitry Andric   return MatchTableRecord(LabelID, "Label " + llvm::to_string(LabelID), 4,
295*0fca6ea1SDimitry Andric                           MatchTableRecord::MTRF_JumpTarget |
296*0fca6ea1SDimitry Andric                               MatchTableRecord::MTRF_Comment |
297*0fca6ea1SDimitry Andric                               MatchTableRecord::MTRF_CommaFollows);
298*0fca6ea1SDimitry Andric }
299*0fca6ea1SDimitry Andric 
300*0fca6ea1SDimitry Andric void MatchTable::emitUse(raw_ostream &OS) const { OS << "MatchTable" << ID; }
301*0fca6ea1SDimitry Andric 
302*0fca6ea1SDimitry Andric void MatchTable::emitDeclaration(raw_ostream &OS) const {
303*0fca6ea1SDimitry Andric   unsigned Indentation = 4;
304*0fca6ea1SDimitry Andric   OS << "  constexpr static uint8_t MatchTable" << ID << "[] = {";
305*0fca6ea1SDimitry Andric   LineBreak.emit(OS, true, *this);
306*0fca6ea1SDimitry Andric   OS << std::string(Indentation, ' ');
307*0fca6ea1SDimitry Andric 
308*0fca6ea1SDimitry Andric   for (auto I = Contents.begin(), E = Contents.end(); I != E; ++I) {
309*0fca6ea1SDimitry Andric     bool LineBreakIsNext = false;
310*0fca6ea1SDimitry Andric     const auto &NextI = std::next(I);
311*0fca6ea1SDimitry Andric 
312*0fca6ea1SDimitry Andric     if (NextI != E) {
313*0fca6ea1SDimitry Andric       if (NextI->EmitStr == "" &&
314*0fca6ea1SDimitry Andric           NextI->Flags == MatchTableRecord::MTRF_LineBreakFollows)
315*0fca6ea1SDimitry Andric         LineBreakIsNext = true;
316*0fca6ea1SDimitry Andric     }
317*0fca6ea1SDimitry Andric 
318*0fca6ea1SDimitry Andric     if (I->Flags & MatchTableRecord::MTRF_Indent)
319*0fca6ea1SDimitry Andric       Indentation += 2;
320*0fca6ea1SDimitry Andric 
321*0fca6ea1SDimitry Andric     I->emit(OS, LineBreakIsNext, *this);
322*0fca6ea1SDimitry Andric     if (I->Flags & MatchTableRecord::MTRF_LineBreakFollows)
323*0fca6ea1SDimitry Andric       OS << std::string(Indentation, ' ');
324*0fca6ea1SDimitry Andric 
325*0fca6ea1SDimitry Andric     if (I->Flags & MatchTableRecord::MTRF_Outdent)
326*0fca6ea1SDimitry Andric       Indentation -= 2;
327*0fca6ea1SDimitry Andric   }
328*0fca6ea1SDimitry Andric   OS << "}; // Size: " << CurrentSize << " bytes\n";
329*0fca6ea1SDimitry Andric }
330*0fca6ea1SDimitry Andric 
331*0fca6ea1SDimitry Andric MatchTable MatchTable::buildTable(ArrayRef<Matcher *> Rules, bool WithCoverage,
332*0fca6ea1SDimitry Andric                                   bool IsCombiner) {
333*0fca6ea1SDimitry Andric   MatchTable Table(WithCoverage, IsCombiner);
334*0fca6ea1SDimitry Andric   for (Matcher *Rule : Rules)
335*0fca6ea1SDimitry Andric     Rule->emit(Table);
336*0fca6ea1SDimitry Andric 
337*0fca6ea1SDimitry Andric   return Table << MatchTable::Opcode("GIM_Reject") << MatchTable::LineBreak;
338*0fca6ea1SDimitry Andric }
339*0fca6ea1SDimitry Andric 
340*0fca6ea1SDimitry Andric //===- LLTCodeGen ---------------------------------------------------------===//
341*0fca6ea1SDimitry Andric 
342*0fca6ea1SDimitry Andric std::string LLTCodeGen::getCxxEnumValue() const {
343*0fca6ea1SDimitry Andric   std::string Str;
344*0fca6ea1SDimitry Andric   raw_string_ostream OS(Str);
345*0fca6ea1SDimitry Andric 
346*0fca6ea1SDimitry Andric   emitCxxEnumValue(OS);
347*0fca6ea1SDimitry Andric   return Str;
348*0fca6ea1SDimitry Andric }
349*0fca6ea1SDimitry Andric 
350*0fca6ea1SDimitry Andric void LLTCodeGen::emitCxxEnumValue(raw_ostream &OS) const {
351*0fca6ea1SDimitry Andric   if (Ty.isScalar()) {
352*0fca6ea1SDimitry Andric     OS << "GILLT_s" << Ty.getSizeInBits();
353*0fca6ea1SDimitry Andric     return;
354*0fca6ea1SDimitry Andric   }
355*0fca6ea1SDimitry Andric   if (Ty.isVector()) {
356*0fca6ea1SDimitry Andric     OS << (Ty.isScalable() ? "GILLT_nxv" : "GILLT_v")
357*0fca6ea1SDimitry Andric        << Ty.getElementCount().getKnownMinValue() << "s"
358*0fca6ea1SDimitry Andric        << Ty.getScalarSizeInBits();
359*0fca6ea1SDimitry Andric     return;
360*0fca6ea1SDimitry Andric   }
361*0fca6ea1SDimitry Andric   if (Ty.isPointer()) {
362*0fca6ea1SDimitry Andric     OS << "GILLT_p" << Ty.getAddressSpace();
363*0fca6ea1SDimitry Andric     if (Ty.getSizeInBits() > 0)
364*0fca6ea1SDimitry Andric       OS << "s" << Ty.getSizeInBits();
365*0fca6ea1SDimitry Andric     return;
366*0fca6ea1SDimitry Andric   }
367*0fca6ea1SDimitry Andric   llvm_unreachable("Unhandled LLT");
368*0fca6ea1SDimitry Andric }
369*0fca6ea1SDimitry Andric 
370*0fca6ea1SDimitry Andric void LLTCodeGen::emitCxxConstructorCall(raw_ostream &OS) const {
371*0fca6ea1SDimitry Andric   if (Ty.isScalar()) {
372*0fca6ea1SDimitry Andric     OS << "LLT::scalar(" << Ty.getSizeInBits() << ")";
373*0fca6ea1SDimitry Andric     return;
374*0fca6ea1SDimitry Andric   }
375*0fca6ea1SDimitry Andric   if (Ty.isVector()) {
376*0fca6ea1SDimitry Andric     OS << "LLT::vector("
377*0fca6ea1SDimitry Andric        << (Ty.isScalable() ? "ElementCount::getScalable("
378*0fca6ea1SDimitry Andric                            : "ElementCount::getFixed(")
379*0fca6ea1SDimitry Andric        << Ty.getElementCount().getKnownMinValue() << "), "
380*0fca6ea1SDimitry Andric        << Ty.getScalarSizeInBits() << ")";
381*0fca6ea1SDimitry Andric     return;
382*0fca6ea1SDimitry Andric   }
383*0fca6ea1SDimitry Andric   if (Ty.isPointer() && Ty.getSizeInBits() > 0) {
384*0fca6ea1SDimitry Andric     OS << "LLT::pointer(" << Ty.getAddressSpace() << ", " << Ty.getSizeInBits()
385*0fca6ea1SDimitry Andric        << ")";
386*0fca6ea1SDimitry Andric     return;
387*0fca6ea1SDimitry Andric   }
388*0fca6ea1SDimitry Andric   llvm_unreachable("Unhandled LLT");
389*0fca6ea1SDimitry Andric }
390*0fca6ea1SDimitry Andric 
391*0fca6ea1SDimitry Andric /// This ordering is used for std::unique() and llvm::sort(). There's no
392*0fca6ea1SDimitry Andric /// particular logic behind the order but either A < B or B < A must be
393*0fca6ea1SDimitry Andric /// true if A != B.
394*0fca6ea1SDimitry Andric bool LLTCodeGen::operator<(const LLTCodeGen &Other) const {
395*0fca6ea1SDimitry Andric   if (Ty.isValid() != Other.Ty.isValid())
396*0fca6ea1SDimitry Andric     return Ty.isValid() < Other.Ty.isValid();
397*0fca6ea1SDimitry Andric   if (!Ty.isValid())
398*0fca6ea1SDimitry Andric     return false;
399*0fca6ea1SDimitry Andric 
400*0fca6ea1SDimitry Andric   if (Ty.isVector() != Other.Ty.isVector())
401*0fca6ea1SDimitry Andric     return Ty.isVector() < Other.Ty.isVector();
402*0fca6ea1SDimitry Andric   if (Ty.isScalar() != Other.Ty.isScalar())
403*0fca6ea1SDimitry Andric     return Ty.isScalar() < Other.Ty.isScalar();
404*0fca6ea1SDimitry Andric   if (Ty.isPointer() != Other.Ty.isPointer())
405*0fca6ea1SDimitry Andric     return Ty.isPointer() < Other.Ty.isPointer();
406*0fca6ea1SDimitry Andric 
407*0fca6ea1SDimitry Andric   if (Ty.isPointer() && Ty.getAddressSpace() != Other.Ty.getAddressSpace())
408*0fca6ea1SDimitry Andric     return Ty.getAddressSpace() < Other.Ty.getAddressSpace();
409*0fca6ea1SDimitry Andric 
410*0fca6ea1SDimitry Andric   if (Ty.isVector() && Ty.getElementCount() != Other.Ty.getElementCount())
411*0fca6ea1SDimitry Andric     return std::tuple(Ty.isScalable(),
412*0fca6ea1SDimitry Andric                       Ty.getElementCount().getKnownMinValue()) <
413*0fca6ea1SDimitry Andric            std::tuple(Other.Ty.isScalable(),
414*0fca6ea1SDimitry Andric                       Other.Ty.getElementCount().getKnownMinValue());
415*0fca6ea1SDimitry Andric 
416*0fca6ea1SDimitry Andric   assert((!Ty.isVector() || Ty.isScalable() == Other.Ty.isScalable()) &&
417*0fca6ea1SDimitry Andric          "Unexpected mismatch of scalable property");
418*0fca6ea1SDimitry Andric   return Ty.isVector()
419*0fca6ea1SDimitry Andric              ? std::tuple(Ty.isScalable(),
420*0fca6ea1SDimitry Andric                           Ty.getSizeInBits().getKnownMinValue()) <
421*0fca6ea1SDimitry Andric                    std::tuple(Other.Ty.isScalable(),
422*0fca6ea1SDimitry Andric                               Other.Ty.getSizeInBits().getKnownMinValue())
423*0fca6ea1SDimitry Andric              : Ty.getSizeInBits().getFixedValue() <
424*0fca6ea1SDimitry Andric                    Other.Ty.getSizeInBits().getFixedValue();
425*0fca6ea1SDimitry Andric }
426*0fca6ea1SDimitry Andric 
427*0fca6ea1SDimitry Andric //===- LLTCodeGen Helpers -------------------------------------------------===//
428*0fca6ea1SDimitry Andric 
429*0fca6ea1SDimitry Andric std::optional<LLTCodeGen> MVTToLLT(MVT::SimpleValueType SVT) {
430*0fca6ea1SDimitry Andric   MVT VT(SVT);
431*0fca6ea1SDimitry Andric 
432*0fca6ea1SDimitry Andric   if (VT.isVector() && !VT.getVectorElementCount().isScalar())
433*0fca6ea1SDimitry Andric     return LLTCodeGen(
434*0fca6ea1SDimitry Andric         LLT::vector(VT.getVectorElementCount(), VT.getScalarSizeInBits()));
435*0fca6ea1SDimitry Andric 
436*0fca6ea1SDimitry Andric   if (VT.isInteger() || VT.isFloatingPoint())
437*0fca6ea1SDimitry Andric     return LLTCodeGen(LLT::scalar(VT.getSizeInBits()));
438*0fca6ea1SDimitry Andric 
439*0fca6ea1SDimitry Andric   return std::nullopt;
440*0fca6ea1SDimitry Andric }
441*0fca6ea1SDimitry Andric 
442*0fca6ea1SDimitry Andric //===- Matcher ------------------------------------------------------------===//
443*0fca6ea1SDimitry Andric 
444*0fca6ea1SDimitry Andric void Matcher::optimize() {}
445*0fca6ea1SDimitry Andric 
446*0fca6ea1SDimitry Andric Matcher::~Matcher() {}
447*0fca6ea1SDimitry Andric 
448*0fca6ea1SDimitry Andric //===- GroupMatcher -------------------------------------------------------===//
449*0fca6ea1SDimitry Andric 
450*0fca6ea1SDimitry Andric bool GroupMatcher::candidateConditionMatches(
451*0fca6ea1SDimitry Andric     const PredicateMatcher &Predicate) const {
452*0fca6ea1SDimitry Andric 
453*0fca6ea1SDimitry Andric   if (empty()) {
454*0fca6ea1SDimitry Andric     // Sharing predicates for nested instructions is not supported yet as we
455*0fca6ea1SDimitry Andric     // currently don't hoist the GIM_RecordInsn's properly, therefore we can
456*0fca6ea1SDimitry Andric     // only work on the original root instruction (InsnVarID == 0):
457*0fca6ea1SDimitry Andric     if (Predicate.getInsnVarID() != 0)
458*0fca6ea1SDimitry Andric       return false;
459*0fca6ea1SDimitry Andric     // ... otherwise an empty group can handle any predicate with no specific
460*0fca6ea1SDimitry Andric     // requirements:
461*0fca6ea1SDimitry Andric     return true;
462*0fca6ea1SDimitry Andric   }
463*0fca6ea1SDimitry Andric 
464*0fca6ea1SDimitry Andric   const Matcher &Representative = **Matchers.begin();
465*0fca6ea1SDimitry Andric   const auto &RepresentativeCondition = Representative.getFirstCondition();
466*0fca6ea1SDimitry Andric   // ... if not empty, the group can only accomodate matchers with the exact
467*0fca6ea1SDimitry Andric   // same first condition:
468*0fca6ea1SDimitry Andric   return Predicate.isIdentical(RepresentativeCondition);
469*0fca6ea1SDimitry Andric }
470*0fca6ea1SDimitry Andric 
471*0fca6ea1SDimitry Andric bool GroupMatcher::addMatcher(Matcher &Candidate) {
472*0fca6ea1SDimitry Andric   if (!Candidate.hasFirstCondition())
473*0fca6ea1SDimitry Andric     return false;
474*0fca6ea1SDimitry Andric 
475*0fca6ea1SDimitry Andric   const PredicateMatcher &Predicate = Candidate.getFirstCondition();
476*0fca6ea1SDimitry Andric   if (!candidateConditionMatches(Predicate))
477*0fca6ea1SDimitry Andric     return false;
478*0fca6ea1SDimitry Andric 
479*0fca6ea1SDimitry Andric   Matchers.push_back(&Candidate);
480*0fca6ea1SDimitry Andric   return true;
481*0fca6ea1SDimitry Andric }
482*0fca6ea1SDimitry Andric 
483*0fca6ea1SDimitry Andric void GroupMatcher::finalize() {
484*0fca6ea1SDimitry Andric   assert(Conditions.empty() && "Already finalized?");
485*0fca6ea1SDimitry Andric   if (empty())
486*0fca6ea1SDimitry Andric     return;
487*0fca6ea1SDimitry Andric 
488*0fca6ea1SDimitry Andric   Matcher &FirstRule = **Matchers.begin();
489*0fca6ea1SDimitry Andric   for (;;) {
490*0fca6ea1SDimitry Andric     // All the checks are expected to succeed during the first iteration:
491*0fca6ea1SDimitry Andric     for (const auto &Rule : Matchers)
492*0fca6ea1SDimitry Andric       if (!Rule->hasFirstCondition())
493*0fca6ea1SDimitry Andric         return;
494*0fca6ea1SDimitry Andric     const auto &FirstCondition = FirstRule.getFirstCondition();
495*0fca6ea1SDimitry Andric     for (unsigned I = 1, E = Matchers.size(); I < E; ++I)
496*0fca6ea1SDimitry Andric       if (!Matchers[I]->getFirstCondition().isIdentical(FirstCondition))
497*0fca6ea1SDimitry Andric         return;
498*0fca6ea1SDimitry Andric 
499*0fca6ea1SDimitry Andric     Conditions.push_back(FirstRule.popFirstCondition());
500*0fca6ea1SDimitry Andric     for (unsigned I = 1, E = Matchers.size(); I < E; ++I)
501*0fca6ea1SDimitry Andric       Matchers[I]->popFirstCondition();
502*0fca6ea1SDimitry Andric   }
503*0fca6ea1SDimitry Andric }
504*0fca6ea1SDimitry Andric 
505*0fca6ea1SDimitry Andric void GroupMatcher::emit(MatchTable &Table) {
506*0fca6ea1SDimitry Andric   unsigned LabelID = ~0U;
507*0fca6ea1SDimitry Andric   if (!Conditions.empty()) {
508*0fca6ea1SDimitry Andric     LabelID = Table.allocateLabelID();
509*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_Try", +1)
510*0fca6ea1SDimitry Andric           << MatchTable::Comment("On fail goto")
511*0fca6ea1SDimitry Andric           << MatchTable::JumpTarget(LabelID) << MatchTable::LineBreak;
512*0fca6ea1SDimitry Andric   }
513*0fca6ea1SDimitry Andric   for (auto &Condition : Conditions)
514*0fca6ea1SDimitry Andric     Condition->emitPredicateOpcodes(
515*0fca6ea1SDimitry Andric         Table, *static_cast<RuleMatcher *>(*Matchers.begin()));
516*0fca6ea1SDimitry Andric 
517*0fca6ea1SDimitry Andric   for (const auto &M : Matchers)
518*0fca6ea1SDimitry Andric     M->emit(Table);
519*0fca6ea1SDimitry Andric 
520*0fca6ea1SDimitry Andric   // Exit the group
521*0fca6ea1SDimitry Andric   if (!Conditions.empty())
522*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_Reject", -1) << MatchTable::LineBreak
523*0fca6ea1SDimitry Andric           << MatchTable::Label(LabelID);
524*0fca6ea1SDimitry Andric }
525*0fca6ea1SDimitry Andric 
526*0fca6ea1SDimitry Andric void GroupMatcher::optimize() {
527*0fca6ea1SDimitry Andric   // Make sure we only sort by a specific predicate within a range of rules that
528*0fca6ea1SDimitry Andric   // all have that predicate checked against a specific value (not a wildcard):
529*0fca6ea1SDimitry Andric   auto F = Matchers.begin();
530*0fca6ea1SDimitry Andric   auto T = F;
531*0fca6ea1SDimitry Andric   auto E = Matchers.end();
532*0fca6ea1SDimitry Andric   while (T != E) {
533*0fca6ea1SDimitry Andric     while (T != E) {
534*0fca6ea1SDimitry Andric       auto *R = static_cast<RuleMatcher *>(*T);
535*0fca6ea1SDimitry Andric       if (!R->getFirstConditionAsRootType().get().isValid())
536*0fca6ea1SDimitry Andric         break;
537*0fca6ea1SDimitry Andric       ++T;
538*0fca6ea1SDimitry Andric     }
539*0fca6ea1SDimitry Andric     std::stable_sort(F, T, [](Matcher *A, Matcher *B) {
540*0fca6ea1SDimitry Andric       auto *L = static_cast<RuleMatcher *>(A);
541*0fca6ea1SDimitry Andric       auto *R = static_cast<RuleMatcher *>(B);
542*0fca6ea1SDimitry Andric       return L->getFirstConditionAsRootType() <
543*0fca6ea1SDimitry Andric              R->getFirstConditionAsRootType();
544*0fca6ea1SDimitry Andric     });
545*0fca6ea1SDimitry Andric     if (T != E)
546*0fca6ea1SDimitry Andric       F = ++T;
547*0fca6ea1SDimitry Andric   }
548*0fca6ea1SDimitry Andric   Matchers = optimizeRules<GroupMatcher>(Matchers, MatcherStorage);
549*0fca6ea1SDimitry Andric   Matchers = optimizeRules<SwitchMatcher>(Matchers, MatcherStorage);
550*0fca6ea1SDimitry Andric }
551*0fca6ea1SDimitry Andric 
552*0fca6ea1SDimitry Andric //===- SwitchMatcher ------------------------------------------------------===//
553*0fca6ea1SDimitry Andric 
554*0fca6ea1SDimitry Andric bool SwitchMatcher::isSupportedPredicateType(const PredicateMatcher &P) {
555*0fca6ea1SDimitry Andric   return isa<InstructionOpcodeMatcher>(P) || isa<LLTOperandMatcher>(P);
556*0fca6ea1SDimitry Andric }
557*0fca6ea1SDimitry Andric 
558*0fca6ea1SDimitry Andric bool SwitchMatcher::candidateConditionMatches(
559*0fca6ea1SDimitry Andric     const PredicateMatcher &Predicate) const {
560*0fca6ea1SDimitry Andric 
561*0fca6ea1SDimitry Andric   if (empty()) {
562*0fca6ea1SDimitry Andric     // Sharing predicates for nested instructions is not supported yet as we
563*0fca6ea1SDimitry Andric     // currently don't hoist the GIM_RecordInsn's properly, therefore we can
564*0fca6ea1SDimitry Andric     // only work on the original root instruction (InsnVarID == 0):
565*0fca6ea1SDimitry Andric     if (Predicate.getInsnVarID() != 0)
566*0fca6ea1SDimitry Andric       return false;
567*0fca6ea1SDimitry Andric     // ... while an attempt to add even a root matcher to an empty SwitchMatcher
568*0fca6ea1SDimitry Andric     // could fail as not all the types of conditions are supported:
569*0fca6ea1SDimitry Andric     if (!isSupportedPredicateType(Predicate))
570*0fca6ea1SDimitry Andric       return false;
571*0fca6ea1SDimitry Andric     // ... or the condition might not have a proper implementation of
572*0fca6ea1SDimitry Andric     // getValue() / isIdenticalDownToValue() yet:
573*0fca6ea1SDimitry Andric     if (!Predicate.hasValue())
574*0fca6ea1SDimitry Andric       return false;
575*0fca6ea1SDimitry Andric     // ... otherwise an empty Switch can accomodate the condition with no
576*0fca6ea1SDimitry Andric     // further requirements:
577*0fca6ea1SDimitry Andric     return true;
578*0fca6ea1SDimitry Andric   }
579*0fca6ea1SDimitry Andric 
580*0fca6ea1SDimitry Andric   const Matcher &CaseRepresentative = **Matchers.begin();
581*0fca6ea1SDimitry Andric   const auto &RepresentativeCondition = CaseRepresentative.getFirstCondition();
582*0fca6ea1SDimitry Andric   // Switch-cases must share the same kind of condition and path to the value it
583*0fca6ea1SDimitry Andric   // checks:
584*0fca6ea1SDimitry Andric   if (!Predicate.isIdenticalDownToValue(RepresentativeCondition))
585*0fca6ea1SDimitry Andric     return false;
586*0fca6ea1SDimitry Andric 
587*0fca6ea1SDimitry Andric   const auto Value = Predicate.getValue();
588*0fca6ea1SDimitry Andric   // ... but be unique with respect to the actual value they check:
589*0fca6ea1SDimitry Andric   return Values.count(Value) == 0;
590*0fca6ea1SDimitry Andric }
591*0fca6ea1SDimitry Andric 
592*0fca6ea1SDimitry Andric bool SwitchMatcher::addMatcher(Matcher &Candidate) {
593*0fca6ea1SDimitry Andric   if (!Candidate.hasFirstCondition())
594*0fca6ea1SDimitry Andric     return false;
595*0fca6ea1SDimitry Andric 
596*0fca6ea1SDimitry Andric   const PredicateMatcher &Predicate = Candidate.getFirstCondition();
597*0fca6ea1SDimitry Andric   if (!candidateConditionMatches(Predicate))
598*0fca6ea1SDimitry Andric     return false;
599*0fca6ea1SDimitry Andric   const auto Value = Predicate.getValue();
600*0fca6ea1SDimitry Andric   Values.insert(Value);
601*0fca6ea1SDimitry Andric 
602*0fca6ea1SDimitry Andric   Matchers.push_back(&Candidate);
603*0fca6ea1SDimitry Andric   return true;
604*0fca6ea1SDimitry Andric }
605*0fca6ea1SDimitry Andric 
606*0fca6ea1SDimitry Andric void SwitchMatcher::finalize() {
607*0fca6ea1SDimitry Andric   assert(Condition == nullptr && "Already finalized");
608*0fca6ea1SDimitry Andric   assert(Values.size() == Matchers.size() && "Broken SwitchMatcher");
609*0fca6ea1SDimitry Andric   if (empty())
610*0fca6ea1SDimitry Andric     return;
611*0fca6ea1SDimitry Andric 
612*0fca6ea1SDimitry Andric   llvm::stable_sort(Matchers, [](const Matcher *L, const Matcher *R) {
613*0fca6ea1SDimitry Andric     return L->getFirstCondition().getValue() <
614*0fca6ea1SDimitry Andric            R->getFirstCondition().getValue();
615*0fca6ea1SDimitry Andric   });
616*0fca6ea1SDimitry Andric   Condition = Matchers[0]->popFirstCondition();
617*0fca6ea1SDimitry Andric   for (unsigned I = 1, E = Values.size(); I < E; ++I)
618*0fca6ea1SDimitry Andric     Matchers[I]->popFirstCondition();
619*0fca6ea1SDimitry Andric }
620*0fca6ea1SDimitry Andric 
621*0fca6ea1SDimitry Andric void SwitchMatcher::emitPredicateSpecificOpcodes(const PredicateMatcher &P,
622*0fca6ea1SDimitry Andric                                                  MatchTable &Table) {
623*0fca6ea1SDimitry Andric   assert(isSupportedPredicateType(P) && "Predicate type is not supported");
624*0fca6ea1SDimitry Andric 
625*0fca6ea1SDimitry Andric   if (const auto *Condition = dyn_cast<InstructionOpcodeMatcher>(&P)) {
626*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_SwitchOpcode") << MatchTable::Comment("MI")
627*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(Condition->getInsnVarID());
628*0fca6ea1SDimitry Andric     return;
629*0fca6ea1SDimitry Andric   }
630*0fca6ea1SDimitry Andric   if (const auto *Condition = dyn_cast<LLTOperandMatcher>(&P)) {
631*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_SwitchType") << MatchTable::Comment("MI")
632*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(Condition->getInsnVarID())
633*0fca6ea1SDimitry Andric           << MatchTable::Comment("Op")
634*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(Condition->getOpIdx());
635*0fca6ea1SDimitry Andric     return;
636*0fca6ea1SDimitry Andric   }
637*0fca6ea1SDimitry Andric 
638*0fca6ea1SDimitry Andric   llvm_unreachable("emitPredicateSpecificOpcodes is broken: can not handle a "
639*0fca6ea1SDimitry Andric                    "predicate type that is claimed to be supported");
640*0fca6ea1SDimitry Andric }
641*0fca6ea1SDimitry Andric 
642*0fca6ea1SDimitry Andric void SwitchMatcher::emit(MatchTable &Table) {
643*0fca6ea1SDimitry Andric   assert(Values.size() == Matchers.size() && "Broken SwitchMatcher");
644*0fca6ea1SDimitry Andric   if (empty())
645*0fca6ea1SDimitry Andric     return;
646*0fca6ea1SDimitry Andric   assert(Condition != nullptr &&
647*0fca6ea1SDimitry Andric          "Broken SwitchMatcher, hasn't been finalized?");
648*0fca6ea1SDimitry Andric 
649*0fca6ea1SDimitry Andric   std::vector<unsigned> LabelIDs(Values.size());
650*0fca6ea1SDimitry Andric   std::generate(LabelIDs.begin(), LabelIDs.end(),
651*0fca6ea1SDimitry Andric                 [&Table]() { return Table.allocateLabelID(); });
652*0fca6ea1SDimitry Andric   const unsigned Default = Table.allocateLabelID();
653*0fca6ea1SDimitry Andric 
654*0fca6ea1SDimitry Andric   const int64_t LowerBound = Values.begin()->getRawValue();
655*0fca6ea1SDimitry Andric   const int64_t UpperBound = Values.rbegin()->getRawValue() + 1;
656*0fca6ea1SDimitry Andric 
657*0fca6ea1SDimitry Andric   emitPredicateSpecificOpcodes(*Condition, Table);
658*0fca6ea1SDimitry Andric 
659*0fca6ea1SDimitry Andric   Table << MatchTable::Comment("[") << MatchTable::IntValue(2, LowerBound)
660*0fca6ea1SDimitry Andric         << MatchTable::IntValue(2, UpperBound) << MatchTable::Comment(")")
661*0fca6ea1SDimitry Andric         << MatchTable::Comment("default:") << MatchTable::JumpTarget(Default);
662*0fca6ea1SDimitry Andric 
663*0fca6ea1SDimitry Andric   int64_t J = LowerBound;
664*0fca6ea1SDimitry Andric   auto VI = Values.begin();
665*0fca6ea1SDimitry Andric   for (unsigned I = 0, E = Values.size(); I < E; ++I) {
666*0fca6ea1SDimitry Andric     auto V = *VI++;
667*0fca6ea1SDimitry Andric     while (J++ < V.getRawValue())
668*0fca6ea1SDimitry Andric       Table << MatchTable::IntValue(4, 0);
669*0fca6ea1SDimitry Andric     V.turnIntoComment();
670*0fca6ea1SDimitry Andric     Table << MatchTable::LineBreak << V << MatchTable::JumpTarget(LabelIDs[I]);
671*0fca6ea1SDimitry Andric   }
672*0fca6ea1SDimitry Andric   Table << MatchTable::LineBreak;
673*0fca6ea1SDimitry Andric 
674*0fca6ea1SDimitry Andric   for (unsigned I = 0, E = Values.size(); I < E; ++I) {
675*0fca6ea1SDimitry Andric     Table << MatchTable::Label(LabelIDs[I]);
676*0fca6ea1SDimitry Andric     Matchers[I]->emit(Table);
677*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_Reject") << MatchTable::LineBreak;
678*0fca6ea1SDimitry Andric   }
679*0fca6ea1SDimitry Andric   Table << MatchTable::Label(Default);
680*0fca6ea1SDimitry Andric }
681*0fca6ea1SDimitry Andric 
682*0fca6ea1SDimitry Andric //===- RuleMatcher --------------------------------------------------------===//
683*0fca6ea1SDimitry Andric 
684*0fca6ea1SDimitry Andric uint64_t RuleMatcher::NextRuleID = 0;
685*0fca6ea1SDimitry Andric 
686*0fca6ea1SDimitry Andric StringRef RuleMatcher::getOpcode() const {
687*0fca6ea1SDimitry Andric   return Matchers.front()->getOpcode();
688*0fca6ea1SDimitry Andric }
689*0fca6ea1SDimitry Andric 
690*0fca6ea1SDimitry Andric unsigned RuleMatcher::getNumOperands() const {
691*0fca6ea1SDimitry Andric   return Matchers.front()->getNumOperands();
692*0fca6ea1SDimitry Andric }
693*0fca6ea1SDimitry Andric 
694*0fca6ea1SDimitry Andric LLTCodeGen RuleMatcher::getFirstConditionAsRootType() {
695*0fca6ea1SDimitry Andric   InstructionMatcher &InsnMatcher = *Matchers.front();
696*0fca6ea1SDimitry Andric   if (!InsnMatcher.predicates_empty())
697*0fca6ea1SDimitry Andric     if (const auto *TM =
698*0fca6ea1SDimitry Andric             dyn_cast<LLTOperandMatcher>(&**InsnMatcher.predicates_begin()))
699*0fca6ea1SDimitry Andric       if (TM->getInsnVarID() == 0 && TM->getOpIdx() == 0)
700*0fca6ea1SDimitry Andric         return TM->getTy();
701*0fca6ea1SDimitry Andric   return {};
702*0fca6ea1SDimitry Andric }
703*0fca6ea1SDimitry Andric 
704*0fca6ea1SDimitry Andric void RuleMatcher::optimize() {
705*0fca6ea1SDimitry Andric   for (auto &Item : InsnVariableIDs) {
706*0fca6ea1SDimitry Andric     InstructionMatcher &InsnMatcher = *Item.first;
707*0fca6ea1SDimitry Andric     for (auto &OM : InsnMatcher.operands()) {
708*0fca6ea1SDimitry Andric       // Complex Patterns are usually expensive and they relatively rarely fail
709*0fca6ea1SDimitry Andric       // on their own: more often we end up throwing away all the work done by a
710*0fca6ea1SDimitry Andric       // matching part of a complex pattern because some other part of the
711*0fca6ea1SDimitry Andric       // enclosing pattern didn't match. All of this makes it beneficial to
712*0fca6ea1SDimitry Andric       // delay complex patterns until the very end of the rule matching,
713*0fca6ea1SDimitry Andric       // especially for targets having lots of complex patterns.
714*0fca6ea1SDimitry Andric       for (auto &OP : OM->predicates())
715*0fca6ea1SDimitry Andric         if (isa<ComplexPatternOperandMatcher>(OP))
716*0fca6ea1SDimitry Andric           EpilogueMatchers.emplace_back(std::move(OP));
717*0fca6ea1SDimitry Andric       OM->eraseNullPredicates();
718*0fca6ea1SDimitry Andric     }
719*0fca6ea1SDimitry Andric     InsnMatcher.optimize();
720*0fca6ea1SDimitry Andric   }
721*0fca6ea1SDimitry Andric   llvm::sort(EpilogueMatchers, [](const std::unique_ptr<PredicateMatcher> &L,
722*0fca6ea1SDimitry Andric                                   const std::unique_ptr<PredicateMatcher> &R) {
723*0fca6ea1SDimitry Andric     return std::tuple(L->getKind(), L->getInsnVarID(), L->getOpIdx()) <
724*0fca6ea1SDimitry Andric            std::tuple(R->getKind(), R->getInsnVarID(), R->getOpIdx());
725*0fca6ea1SDimitry Andric   });
726*0fca6ea1SDimitry Andric 
727*0fca6ea1SDimitry Andric   // Deduplicate EraseInst actions, and if an EraseInst erases the root, place
728*0fca6ea1SDimitry Andric   // it at the end to favor generation of GIR_EraseRootFromParent_Done
729*0fca6ea1SDimitry Andric   DenseSet<unsigned> AlreadySeenEraseInsts;
730*0fca6ea1SDimitry Andric   auto EraseRootIt = Actions.end();
731*0fca6ea1SDimitry Andric   auto It = Actions.begin();
732*0fca6ea1SDimitry Andric   while (It != Actions.end()) {
733*0fca6ea1SDimitry Andric     if (const auto *EI = dyn_cast<EraseInstAction>(It->get())) {
734*0fca6ea1SDimitry Andric       unsigned InstID = EI->getInsnID();
735*0fca6ea1SDimitry Andric       if (!AlreadySeenEraseInsts.insert(InstID).second) {
736*0fca6ea1SDimitry Andric         It = Actions.erase(It);
737*0fca6ea1SDimitry Andric         continue;
738*0fca6ea1SDimitry Andric       }
739*0fca6ea1SDimitry Andric 
740*0fca6ea1SDimitry Andric       if (InstID == 0)
741*0fca6ea1SDimitry Andric         EraseRootIt = It;
742*0fca6ea1SDimitry Andric     }
743*0fca6ea1SDimitry Andric 
744*0fca6ea1SDimitry Andric     ++It;
745*0fca6ea1SDimitry Andric   }
746*0fca6ea1SDimitry Andric 
747*0fca6ea1SDimitry Andric   if (EraseRootIt != Actions.end())
748*0fca6ea1SDimitry Andric     Actions.splice(Actions.end(), Actions, EraseRootIt);
749*0fca6ea1SDimitry Andric }
750*0fca6ea1SDimitry Andric 
751*0fca6ea1SDimitry Andric bool RuleMatcher::hasFirstCondition() const {
752*0fca6ea1SDimitry Andric   if (insnmatchers_empty())
753*0fca6ea1SDimitry Andric     return false;
754*0fca6ea1SDimitry Andric   InstructionMatcher &Matcher = insnmatchers_front();
755*0fca6ea1SDimitry Andric   if (!Matcher.predicates_empty())
756*0fca6ea1SDimitry Andric     return true;
757*0fca6ea1SDimitry Andric   for (auto &OM : Matcher.operands())
758*0fca6ea1SDimitry Andric     for (auto &OP : OM->predicates())
759*0fca6ea1SDimitry Andric       if (!isa<InstructionOperandMatcher>(OP))
760*0fca6ea1SDimitry Andric         return true;
761*0fca6ea1SDimitry Andric   return false;
762*0fca6ea1SDimitry Andric }
763*0fca6ea1SDimitry Andric 
764*0fca6ea1SDimitry Andric const PredicateMatcher &RuleMatcher::getFirstCondition() const {
765*0fca6ea1SDimitry Andric   assert(!insnmatchers_empty() &&
766*0fca6ea1SDimitry Andric          "Trying to get a condition from an empty RuleMatcher");
767*0fca6ea1SDimitry Andric 
768*0fca6ea1SDimitry Andric   InstructionMatcher &Matcher = insnmatchers_front();
769*0fca6ea1SDimitry Andric   if (!Matcher.predicates_empty())
770*0fca6ea1SDimitry Andric     return **Matcher.predicates_begin();
771*0fca6ea1SDimitry Andric   // If there is no more predicate on the instruction itself, look at its
772*0fca6ea1SDimitry Andric   // operands.
773*0fca6ea1SDimitry Andric   for (auto &OM : Matcher.operands())
774*0fca6ea1SDimitry Andric     for (auto &OP : OM->predicates())
775*0fca6ea1SDimitry Andric       if (!isa<InstructionOperandMatcher>(OP))
776*0fca6ea1SDimitry Andric         return *OP;
777*0fca6ea1SDimitry Andric 
778*0fca6ea1SDimitry Andric   llvm_unreachable("Trying to get a condition from an InstructionMatcher with "
779*0fca6ea1SDimitry Andric                    "no conditions");
780*0fca6ea1SDimitry Andric }
781*0fca6ea1SDimitry Andric 
782*0fca6ea1SDimitry Andric std::unique_ptr<PredicateMatcher> RuleMatcher::popFirstCondition() {
783*0fca6ea1SDimitry Andric   assert(!insnmatchers_empty() &&
784*0fca6ea1SDimitry Andric          "Trying to pop a condition from an empty RuleMatcher");
785*0fca6ea1SDimitry Andric 
786*0fca6ea1SDimitry Andric   InstructionMatcher &Matcher = insnmatchers_front();
787*0fca6ea1SDimitry Andric   if (!Matcher.predicates_empty())
788*0fca6ea1SDimitry Andric     return Matcher.predicates_pop_front();
789*0fca6ea1SDimitry Andric   // If there is no more predicate on the instruction itself, look at its
790*0fca6ea1SDimitry Andric   // operands.
791*0fca6ea1SDimitry Andric   for (auto &OM : Matcher.operands())
792*0fca6ea1SDimitry Andric     for (auto &OP : OM->predicates())
793*0fca6ea1SDimitry Andric       if (!isa<InstructionOperandMatcher>(OP)) {
794*0fca6ea1SDimitry Andric         std::unique_ptr<PredicateMatcher> Result = std::move(OP);
795*0fca6ea1SDimitry Andric         OM->eraseNullPredicates();
796*0fca6ea1SDimitry Andric         return Result;
797*0fca6ea1SDimitry Andric       }
798*0fca6ea1SDimitry Andric 
799*0fca6ea1SDimitry Andric   llvm_unreachable("Trying to pop a condition from an InstructionMatcher with "
800*0fca6ea1SDimitry Andric                    "no conditions");
801*0fca6ea1SDimitry Andric }
802*0fca6ea1SDimitry Andric 
803*0fca6ea1SDimitry Andric GISelFlags RuleMatcher::updateGISelFlag(GISelFlags CurFlags, const Record *R,
804*0fca6ea1SDimitry Andric                                         StringRef FlagName,
805*0fca6ea1SDimitry Andric                                         GISelFlags FlagBit) {
806*0fca6ea1SDimitry Andric   // If the value of a flag is unset, ignore it.
807*0fca6ea1SDimitry Andric   // If it's set, it always takes precedence over the existing value so
808*0fca6ea1SDimitry Andric   // clear/set the corresponding bit.
809*0fca6ea1SDimitry Andric   bool Unset = false;
810*0fca6ea1SDimitry Andric   bool Value = R->getValueAsBitOrUnset("GIIgnoreCopies", Unset);
811*0fca6ea1SDimitry Andric   if (!Unset)
812*0fca6ea1SDimitry Andric     return Value ? (CurFlags | FlagBit) : (CurFlags & ~FlagBit);
813*0fca6ea1SDimitry Andric   return CurFlags;
814*0fca6ea1SDimitry Andric }
815*0fca6ea1SDimitry Andric 
816*0fca6ea1SDimitry Andric SaveAndRestore<GISelFlags> RuleMatcher::setGISelFlags(const Record *R) {
817*0fca6ea1SDimitry Andric   if (!R || !R->isSubClassOf("GISelFlags"))
818*0fca6ea1SDimitry Andric     return {Flags, Flags};
819*0fca6ea1SDimitry Andric 
820*0fca6ea1SDimitry Andric   assert((R->isSubClassOf("PatFrags") || R->isSubClassOf("Pattern")) &&
821*0fca6ea1SDimitry Andric          "GISelFlags is only expected on Pattern/PatFrags!");
822*0fca6ea1SDimitry Andric 
823*0fca6ea1SDimitry Andric   GISelFlags NewFlags =
824*0fca6ea1SDimitry Andric       updateGISelFlag(Flags, R, "GIIgnoreCopies", GISF_IgnoreCopies);
825*0fca6ea1SDimitry Andric   return {Flags, NewFlags};
826*0fca6ea1SDimitry Andric }
827*0fca6ea1SDimitry Andric 
828*0fca6ea1SDimitry Andric Error RuleMatcher::defineComplexSubOperand(StringRef SymbolicName,
829*0fca6ea1SDimitry Andric                                            Record *ComplexPattern,
830*0fca6ea1SDimitry Andric                                            unsigned RendererID,
831*0fca6ea1SDimitry Andric                                            unsigned SubOperandID,
832*0fca6ea1SDimitry Andric                                            StringRef ParentSymbolicName) {
833*0fca6ea1SDimitry Andric   std::string ParentName(ParentSymbolicName);
834*0fca6ea1SDimitry Andric   if (ComplexSubOperands.count(SymbolicName)) {
835*0fca6ea1SDimitry Andric     const std::string &RecordedParentName =
836*0fca6ea1SDimitry Andric         ComplexSubOperandsParentName[SymbolicName];
837*0fca6ea1SDimitry Andric     if (RecordedParentName != ParentName)
838*0fca6ea1SDimitry Andric       return failUnsupported("Error: Complex suboperand " + SymbolicName +
839*0fca6ea1SDimitry Andric                              " referenced by different operands: " +
840*0fca6ea1SDimitry Andric                              RecordedParentName + " and " + ParentName + ".");
841*0fca6ea1SDimitry Andric     // Complex suboperand referenced more than once from same the operand is
842*0fca6ea1SDimitry Andric     // used to generate 'same operand check'. Emitting of
843*0fca6ea1SDimitry Andric     // GIR_ComplexSubOperandRenderer for them is already handled.
844*0fca6ea1SDimitry Andric     return Error::success();
845*0fca6ea1SDimitry Andric   }
846*0fca6ea1SDimitry Andric 
847*0fca6ea1SDimitry Andric   ComplexSubOperands[SymbolicName] =
848*0fca6ea1SDimitry Andric       std::tuple(ComplexPattern, RendererID, SubOperandID);
849*0fca6ea1SDimitry Andric   ComplexSubOperandsParentName[SymbolicName] = ParentName;
850*0fca6ea1SDimitry Andric 
851*0fca6ea1SDimitry Andric   return Error::success();
852*0fca6ea1SDimitry Andric }
853*0fca6ea1SDimitry Andric 
854*0fca6ea1SDimitry Andric InstructionMatcher &RuleMatcher::addInstructionMatcher(StringRef SymbolicName) {
855*0fca6ea1SDimitry Andric   Matchers.emplace_back(new InstructionMatcher(*this, SymbolicName));
856*0fca6ea1SDimitry Andric   MutatableInsns.insert(Matchers.back().get());
857*0fca6ea1SDimitry Andric   return *Matchers.back();
858*0fca6ea1SDimitry Andric }
859*0fca6ea1SDimitry Andric 
860*0fca6ea1SDimitry Andric void RuleMatcher::addRequiredSimplePredicate(StringRef PredName) {
861*0fca6ea1SDimitry Andric   RequiredSimplePredicates.push_back(PredName.str());
862*0fca6ea1SDimitry Andric }
863*0fca6ea1SDimitry Andric 
864*0fca6ea1SDimitry Andric const std::vector<std::string> &RuleMatcher::getRequiredSimplePredicates() {
865*0fca6ea1SDimitry Andric   return RequiredSimplePredicates;
866*0fca6ea1SDimitry Andric }
867*0fca6ea1SDimitry Andric 
868*0fca6ea1SDimitry Andric void RuleMatcher::addRequiredFeature(Record *Feature) {
869*0fca6ea1SDimitry Andric   RequiredFeatures.push_back(Feature);
870*0fca6ea1SDimitry Andric }
871*0fca6ea1SDimitry Andric 
872*0fca6ea1SDimitry Andric const std::vector<Record *> &RuleMatcher::getRequiredFeatures() const {
873*0fca6ea1SDimitry Andric   return RequiredFeatures;
874*0fca6ea1SDimitry Andric }
875*0fca6ea1SDimitry Andric 
876*0fca6ea1SDimitry Andric unsigned RuleMatcher::implicitlyDefineInsnVar(InstructionMatcher &Matcher) {
877*0fca6ea1SDimitry Andric   unsigned NewInsnVarID = NextInsnVarID++;
878*0fca6ea1SDimitry Andric   InsnVariableIDs[&Matcher] = NewInsnVarID;
879*0fca6ea1SDimitry Andric   return NewInsnVarID;
880*0fca6ea1SDimitry Andric }
881*0fca6ea1SDimitry Andric 
882*0fca6ea1SDimitry Andric unsigned RuleMatcher::getInsnVarID(InstructionMatcher &InsnMatcher) const {
883*0fca6ea1SDimitry Andric   const auto &I = InsnVariableIDs.find(&InsnMatcher);
884*0fca6ea1SDimitry Andric   if (I != InsnVariableIDs.end())
885*0fca6ea1SDimitry Andric     return I->second;
886*0fca6ea1SDimitry Andric   llvm_unreachable("Matched Insn was not captured in a local variable");
887*0fca6ea1SDimitry Andric }
888*0fca6ea1SDimitry Andric 
889*0fca6ea1SDimitry Andric void RuleMatcher::defineOperand(StringRef SymbolicName, OperandMatcher &OM) {
890*0fca6ea1SDimitry Andric   if (!DefinedOperands.contains(SymbolicName)) {
891*0fca6ea1SDimitry Andric     DefinedOperands[SymbolicName] = &OM;
892*0fca6ea1SDimitry Andric     return;
893*0fca6ea1SDimitry Andric   }
894*0fca6ea1SDimitry Andric 
895*0fca6ea1SDimitry Andric   // If the operand is already defined, then we must ensure both references in
896*0fca6ea1SDimitry Andric   // the matcher have the exact same node.
897*0fca6ea1SDimitry Andric   RuleMatcher &RM = OM.getInstructionMatcher().getRuleMatcher();
898*0fca6ea1SDimitry Andric   OM.addPredicate<SameOperandMatcher>(
899*0fca6ea1SDimitry Andric       OM.getSymbolicName(), getOperandMatcher(OM.getSymbolicName()).getOpIdx(),
900*0fca6ea1SDimitry Andric       RM.getGISelFlags());
901*0fca6ea1SDimitry Andric }
902*0fca6ea1SDimitry Andric 
903*0fca6ea1SDimitry Andric void RuleMatcher::definePhysRegOperand(Record *Reg, OperandMatcher &OM) {
904*0fca6ea1SDimitry Andric   if (!PhysRegOperands.contains(Reg)) {
905*0fca6ea1SDimitry Andric     PhysRegOperands[Reg] = &OM;
906*0fca6ea1SDimitry Andric     return;
907*0fca6ea1SDimitry Andric   }
908*0fca6ea1SDimitry Andric }
909*0fca6ea1SDimitry Andric 
910*0fca6ea1SDimitry Andric InstructionMatcher &
911*0fca6ea1SDimitry Andric RuleMatcher::getInstructionMatcher(StringRef SymbolicName) const {
912*0fca6ea1SDimitry Andric   for (const auto &I : InsnVariableIDs)
913*0fca6ea1SDimitry Andric     if (I.first->getSymbolicName() == SymbolicName)
914*0fca6ea1SDimitry Andric       return *I.first;
915*0fca6ea1SDimitry Andric   llvm_unreachable(
916*0fca6ea1SDimitry Andric       ("Failed to lookup instruction " + SymbolicName).str().c_str());
917*0fca6ea1SDimitry Andric }
918*0fca6ea1SDimitry Andric 
919*0fca6ea1SDimitry Andric const OperandMatcher &RuleMatcher::getPhysRegOperandMatcher(Record *Reg) const {
920*0fca6ea1SDimitry Andric   const auto &I = PhysRegOperands.find(Reg);
921*0fca6ea1SDimitry Andric 
922*0fca6ea1SDimitry Andric   if (I == PhysRegOperands.end()) {
923*0fca6ea1SDimitry Andric     PrintFatalError(SrcLoc, "Register " + Reg->getName() +
924*0fca6ea1SDimitry Andric                                 " was not declared in matcher");
925*0fca6ea1SDimitry Andric   }
926*0fca6ea1SDimitry Andric 
927*0fca6ea1SDimitry Andric   return *I->second;
928*0fca6ea1SDimitry Andric }
929*0fca6ea1SDimitry Andric 
930*0fca6ea1SDimitry Andric OperandMatcher &RuleMatcher::getOperandMatcher(StringRef Name) {
931*0fca6ea1SDimitry Andric   const auto &I = DefinedOperands.find(Name);
932*0fca6ea1SDimitry Andric 
933*0fca6ea1SDimitry Andric   if (I == DefinedOperands.end())
934*0fca6ea1SDimitry Andric     PrintFatalError(SrcLoc, "Operand " + Name + " was not declared in matcher");
935*0fca6ea1SDimitry Andric 
936*0fca6ea1SDimitry Andric   return *I->second;
937*0fca6ea1SDimitry Andric }
938*0fca6ea1SDimitry Andric 
939*0fca6ea1SDimitry Andric const OperandMatcher &RuleMatcher::getOperandMatcher(StringRef Name) const {
940*0fca6ea1SDimitry Andric   const auto &I = DefinedOperands.find(Name);
941*0fca6ea1SDimitry Andric 
942*0fca6ea1SDimitry Andric   if (I == DefinedOperands.end())
943*0fca6ea1SDimitry Andric     PrintFatalError(SrcLoc, "Operand " + Name + " was not declared in matcher");
944*0fca6ea1SDimitry Andric 
945*0fca6ea1SDimitry Andric   return *I->second;
946*0fca6ea1SDimitry Andric }
947*0fca6ea1SDimitry Andric 
948*0fca6ea1SDimitry Andric void RuleMatcher::emit(MatchTable &Table) {
949*0fca6ea1SDimitry Andric   if (Matchers.empty())
950*0fca6ea1SDimitry Andric     llvm_unreachable("Unexpected empty matcher!");
951*0fca6ea1SDimitry Andric 
952*0fca6ea1SDimitry Andric   // The representation supports rules that require multiple roots such as:
953*0fca6ea1SDimitry Andric   //    %ptr(p0) = ...
954*0fca6ea1SDimitry Andric   //    %elt0(s32) = G_LOAD %ptr
955*0fca6ea1SDimitry Andric   //    %1(p0) = G_ADD %ptr, 4
956*0fca6ea1SDimitry Andric   //    %elt1(s32) = G_LOAD p0 %1
957*0fca6ea1SDimitry Andric   // which could be usefully folded into:
958*0fca6ea1SDimitry Andric   //    %ptr(p0) = ...
959*0fca6ea1SDimitry Andric   //    %elt0(s32), %elt1(s32) = TGT_LOAD_PAIR %ptr
960*0fca6ea1SDimitry Andric   // on some targets but we don't need to make use of that yet.
961*0fca6ea1SDimitry Andric   assert(Matchers.size() == 1 && "Cannot handle multi-root matchers yet");
962*0fca6ea1SDimitry Andric 
963*0fca6ea1SDimitry Andric   unsigned LabelID = Table.allocateLabelID();
964*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_Try", +1)
965*0fca6ea1SDimitry Andric         << MatchTable::Comment("On fail goto")
966*0fca6ea1SDimitry Andric         << MatchTable::JumpTarget(LabelID)
967*0fca6ea1SDimitry Andric         << MatchTable::Comment(("Rule ID " + Twine(RuleID) + " //").str())
968*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
969*0fca6ea1SDimitry Andric 
970*0fca6ea1SDimitry Andric   if (!RequiredFeatures.empty() || HwModeIdx >= 0) {
971*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_CheckFeatures")
972*0fca6ea1SDimitry Andric           << MatchTable::NamedValue(
973*0fca6ea1SDimitry Andric                  2, getNameForFeatureBitset(RequiredFeatures, HwModeIdx))
974*0fca6ea1SDimitry Andric           << MatchTable::LineBreak;
975*0fca6ea1SDimitry Andric   }
976*0fca6ea1SDimitry Andric 
977*0fca6ea1SDimitry Andric   if (!RequiredSimplePredicates.empty()) {
978*0fca6ea1SDimitry Andric     for (const auto &Pred : RequiredSimplePredicates) {
979*0fca6ea1SDimitry Andric       Table << MatchTable::Opcode("GIM_CheckSimplePredicate")
980*0fca6ea1SDimitry Andric             << MatchTable::NamedValue(2, Pred) << MatchTable::LineBreak;
981*0fca6ea1SDimitry Andric     }
982*0fca6ea1SDimitry Andric   }
983*0fca6ea1SDimitry Andric 
984*0fca6ea1SDimitry Andric   Matchers.front()->emitPredicateOpcodes(Table, *this);
985*0fca6ea1SDimitry Andric 
986*0fca6ea1SDimitry Andric   // Check if it's safe to replace registers.
987*0fca6ea1SDimitry Andric   for (const auto &MA : Actions)
988*0fca6ea1SDimitry Andric     MA->emitAdditionalPredicates(Table, *this);
989*0fca6ea1SDimitry Andric 
990*0fca6ea1SDimitry Andric   // We must also check if it's safe to fold the matched instructions.
991*0fca6ea1SDimitry Andric   if (InsnVariableIDs.size() >= 2) {
992*0fca6ea1SDimitry Andric 
993*0fca6ea1SDimitry Andric     // FIXME: Emit checks to determine it's _actually_ safe to fold and/or
994*0fca6ea1SDimitry Andric     //        account for unsafe cases.
995*0fca6ea1SDimitry Andric     //
996*0fca6ea1SDimitry Andric     //        Example:
997*0fca6ea1SDimitry Andric     //          MI1--> %0 = ...
998*0fca6ea1SDimitry Andric     //                 %1 = ... %0
999*0fca6ea1SDimitry Andric     //          MI0--> %2 = ... %0
1000*0fca6ea1SDimitry Andric     //          It's not safe to erase MI1. We currently handle this by not
1001*0fca6ea1SDimitry Andric     //          erasing %0 (even when it's dead).
1002*0fca6ea1SDimitry Andric     //
1003*0fca6ea1SDimitry Andric     //        Example:
1004*0fca6ea1SDimitry Andric     //          MI1--> %0 = load volatile @a
1005*0fca6ea1SDimitry Andric     //                 %1 = load volatile @a
1006*0fca6ea1SDimitry Andric     //          MI0--> %2 = ... %0
1007*0fca6ea1SDimitry Andric     //          It's not safe to sink %0's def past %1. We currently handle
1008*0fca6ea1SDimitry Andric     //          this by rejecting all loads.
1009*0fca6ea1SDimitry Andric     //
1010*0fca6ea1SDimitry Andric     //        Example:
1011*0fca6ea1SDimitry Andric     //          MI1--> %0 = load @a
1012*0fca6ea1SDimitry Andric     //                 %1 = store @a
1013*0fca6ea1SDimitry Andric     //          MI0--> %2 = ... %0
1014*0fca6ea1SDimitry Andric     //          It's not safe to sink %0's def past %1. We currently handle
1015*0fca6ea1SDimitry Andric     //          this by rejecting all loads.
1016*0fca6ea1SDimitry Andric     //
1017*0fca6ea1SDimitry Andric     //        Example:
1018*0fca6ea1SDimitry Andric     //                   G_CONDBR %cond, @BB1
1019*0fca6ea1SDimitry Andric     //                 BB0:
1020*0fca6ea1SDimitry Andric     //          MI1-->   %0 = load @a
1021*0fca6ea1SDimitry Andric     //                   G_BR @BB1
1022*0fca6ea1SDimitry Andric     //                 BB1:
1023*0fca6ea1SDimitry Andric     //          MI0-->   %2 = ... %0
1024*0fca6ea1SDimitry Andric     //          It's not always safe to sink %0 across control flow. In this
1025*0fca6ea1SDimitry Andric     //          case it may introduce a memory fault. We currentl handle
1026*0fca6ea1SDimitry Andric     //          this by rejecting all loads.
1027*0fca6ea1SDimitry Andric 
1028*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_CheckIsSafeToFold")
1029*0fca6ea1SDimitry Andric           << MatchTable::Comment("NumInsns")
1030*0fca6ea1SDimitry Andric           << MatchTable::IntValue(1, InsnVariableIDs.size() - 1)
1031*0fca6ea1SDimitry Andric           << MatchTable::LineBreak;
1032*0fca6ea1SDimitry Andric   }
1033*0fca6ea1SDimitry Andric 
1034*0fca6ea1SDimitry Andric   for (const auto &PM : EpilogueMatchers)
1035*0fca6ea1SDimitry Andric     PM->emitPredicateOpcodes(Table, *this);
1036*0fca6ea1SDimitry Andric 
1037*0fca6ea1SDimitry Andric   if (!CustomCXXAction.empty()) {
1038*0fca6ea1SDimitry Andric     /// Handle combiners relying on custom C++ code instead of actions.
1039*0fca6ea1SDimitry Andric     assert(Table.isCombiner() && "CustomCXXAction is only for combiners!");
1040*0fca6ea1SDimitry Andric     // We cannot have actions other than debug comments.
1041*0fca6ea1SDimitry Andric     assert(none_of(Actions, [](auto &A) {
1042*0fca6ea1SDimitry Andric       return A->getKind() != MatchAction::AK_DebugComment;
1043*0fca6ea1SDimitry Andric     }));
1044*0fca6ea1SDimitry Andric     for (const auto &MA : Actions)
1045*0fca6ea1SDimitry Andric       MA->emitActionOpcodes(Table, *this);
1046*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIR_DoneWithCustomAction", -1)
1047*0fca6ea1SDimitry Andric           << MatchTable::Comment("Fn")
1048*0fca6ea1SDimitry Andric           << MatchTable::NamedValue(2, CustomCXXAction)
1049*0fca6ea1SDimitry Andric           << MatchTable::LineBreak;
1050*0fca6ea1SDimitry Andric   } else {
1051*0fca6ea1SDimitry Andric     // Emit all actions except the last one, then emit coverage and emit the
1052*0fca6ea1SDimitry Andric     // final action.
1053*0fca6ea1SDimitry Andric     //
1054*0fca6ea1SDimitry Andric     // This is because some actions, such as GIR_EraseRootFromParent_Done, also
1055*0fca6ea1SDimitry Andric     // double as a GIR_Done and terminate execution of the rule.
1056*0fca6ea1SDimitry Andric     if (!Actions.empty()) {
1057*0fca6ea1SDimitry Andric       for (const auto &MA : drop_end(Actions))
1058*0fca6ea1SDimitry Andric         MA->emitActionOpcodes(Table, *this);
1059*0fca6ea1SDimitry Andric     }
1060*0fca6ea1SDimitry Andric 
1061*0fca6ea1SDimitry Andric     assert((Table.isWithCoverage() ? !Table.isCombiner() : true) &&
1062*0fca6ea1SDimitry Andric            "Combiner tables don't support coverage!");
1063*0fca6ea1SDimitry Andric     if (Table.isWithCoverage())
1064*0fca6ea1SDimitry Andric       Table << MatchTable::Opcode("GIR_Coverage")
1065*0fca6ea1SDimitry Andric             << MatchTable::IntValue(4, RuleID) << MatchTable::LineBreak;
1066*0fca6ea1SDimitry Andric     else if (!Table.isCombiner())
1067*0fca6ea1SDimitry Andric       Table << MatchTable::Comment(
1068*0fca6ea1SDimitry Andric                    ("GIR_Coverage, " + Twine(RuleID) + ",").str())
1069*0fca6ea1SDimitry Andric             << MatchTable::LineBreak;
1070*0fca6ea1SDimitry Andric 
1071*0fca6ea1SDimitry Andric     if (Actions.empty() ||
1072*0fca6ea1SDimitry Andric         !Actions.back()->emitActionOpcodesAndDone(Table, *this)) {
1073*0fca6ea1SDimitry Andric       Table << MatchTable::Opcode("GIR_Done", -1) << MatchTable::LineBreak;
1074*0fca6ea1SDimitry Andric     }
1075*0fca6ea1SDimitry Andric   }
1076*0fca6ea1SDimitry Andric 
1077*0fca6ea1SDimitry Andric   Table << MatchTable::Label(LabelID);
1078*0fca6ea1SDimitry Andric   ++NumPatternEmitted;
1079*0fca6ea1SDimitry Andric }
1080*0fca6ea1SDimitry Andric 
1081*0fca6ea1SDimitry Andric bool RuleMatcher::isHigherPriorityThan(const RuleMatcher &B) const {
1082*0fca6ea1SDimitry Andric   // Rules involving more match roots have higher priority.
1083*0fca6ea1SDimitry Andric   if (Matchers.size() > B.Matchers.size())
1084*0fca6ea1SDimitry Andric     return true;
1085*0fca6ea1SDimitry Andric   if (Matchers.size() < B.Matchers.size())
1086*0fca6ea1SDimitry Andric     return false;
1087*0fca6ea1SDimitry Andric 
1088*0fca6ea1SDimitry Andric   for (auto Matcher : zip(Matchers, B.Matchers)) {
1089*0fca6ea1SDimitry Andric     if (std::get<0>(Matcher)->isHigherPriorityThan(*std::get<1>(Matcher)))
1090*0fca6ea1SDimitry Andric       return true;
1091*0fca6ea1SDimitry Andric     if (std::get<1>(Matcher)->isHigherPriorityThan(*std::get<0>(Matcher)))
1092*0fca6ea1SDimitry Andric       return false;
1093*0fca6ea1SDimitry Andric   }
1094*0fca6ea1SDimitry Andric 
1095*0fca6ea1SDimitry Andric   return false;
1096*0fca6ea1SDimitry Andric }
1097*0fca6ea1SDimitry Andric 
1098*0fca6ea1SDimitry Andric unsigned RuleMatcher::countRendererFns() const {
1099*0fca6ea1SDimitry Andric   return std::accumulate(
1100*0fca6ea1SDimitry Andric       Matchers.begin(), Matchers.end(), 0,
1101*0fca6ea1SDimitry Andric       [](unsigned A, const std::unique_ptr<InstructionMatcher> &Matcher) {
1102*0fca6ea1SDimitry Andric         return A + Matcher->countRendererFns();
1103*0fca6ea1SDimitry Andric       });
1104*0fca6ea1SDimitry Andric }
1105*0fca6ea1SDimitry Andric 
1106*0fca6ea1SDimitry Andric //===- PredicateMatcher ---------------------------------------------------===//
1107*0fca6ea1SDimitry Andric 
1108*0fca6ea1SDimitry Andric PredicateMatcher::~PredicateMatcher() {}
1109*0fca6ea1SDimitry Andric 
1110*0fca6ea1SDimitry Andric //===- OperandPredicateMatcher --------------------------------------------===//
1111*0fca6ea1SDimitry Andric 
1112*0fca6ea1SDimitry Andric OperandPredicateMatcher::~OperandPredicateMatcher() {}
1113*0fca6ea1SDimitry Andric 
1114*0fca6ea1SDimitry Andric bool OperandPredicateMatcher::isHigherPriorityThan(
1115*0fca6ea1SDimitry Andric     const OperandPredicateMatcher &B) const {
1116*0fca6ea1SDimitry Andric   // Generally speaking, an instruction is more important than an Int or a
1117*0fca6ea1SDimitry Andric   // LiteralInt because it can cover more nodes but there's an exception to
1118*0fca6ea1SDimitry Andric   // this. G_CONSTANT's are less important than either of those two because they
1119*0fca6ea1SDimitry Andric   // are more permissive.
1120*0fca6ea1SDimitry Andric 
1121*0fca6ea1SDimitry Andric   const auto *AOM = dyn_cast<InstructionOperandMatcher>(this);
1122*0fca6ea1SDimitry Andric   const auto *BOM = dyn_cast<InstructionOperandMatcher>(&B);
1123*0fca6ea1SDimitry Andric   bool AIsConstantInsn = AOM && AOM->getInsnMatcher().isConstantInstruction();
1124*0fca6ea1SDimitry Andric   bool BIsConstantInsn = BOM && BOM->getInsnMatcher().isConstantInstruction();
1125*0fca6ea1SDimitry Andric 
1126*0fca6ea1SDimitry Andric   // The relative priorities between a G_CONSTANT and any other instruction
1127*0fca6ea1SDimitry Andric   // don't actually matter but this code is needed to ensure a strict weak
1128*0fca6ea1SDimitry Andric   // ordering. This is particularly important on Windows where the rules will
1129*0fca6ea1SDimitry Andric   // be incorrectly sorted without it.
1130*0fca6ea1SDimitry Andric   if (AOM && BOM)
1131*0fca6ea1SDimitry Andric     return !AIsConstantInsn && BIsConstantInsn;
1132*0fca6ea1SDimitry Andric 
1133*0fca6ea1SDimitry Andric   if (AIsConstantInsn && (B.Kind == OPM_Int || B.Kind == OPM_LiteralInt))
1134*0fca6ea1SDimitry Andric     return false;
1135*0fca6ea1SDimitry Andric   if (BIsConstantInsn && (Kind == OPM_Int || Kind == OPM_LiteralInt))
1136*0fca6ea1SDimitry Andric     return true;
1137*0fca6ea1SDimitry Andric 
1138*0fca6ea1SDimitry Andric   return Kind < B.Kind;
1139*0fca6ea1SDimitry Andric }
1140*0fca6ea1SDimitry Andric 
1141*0fca6ea1SDimitry Andric //===- SameOperandMatcher -------------------------------------------------===//
1142*0fca6ea1SDimitry Andric 
1143*0fca6ea1SDimitry Andric void SameOperandMatcher::emitPredicateOpcodes(MatchTable &Table,
1144*0fca6ea1SDimitry Andric                                               RuleMatcher &Rule) const {
1145*0fca6ea1SDimitry Andric   const OperandMatcher &OtherOM = Rule.getOperandMatcher(MatchingName);
1146*0fca6ea1SDimitry Andric   unsigned OtherInsnVarID = Rule.getInsnVarID(OtherOM.getInstructionMatcher());
1147*0fca6ea1SDimitry Andric   assert(OtherInsnVarID == OtherOM.getInstructionMatcher().getInsnVarID());
1148*0fca6ea1SDimitry Andric   const bool IgnoreCopies = Flags & GISF_IgnoreCopies;
1149*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode(IgnoreCopies
1150*0fca6ea1SDimitry Andric                                   ? "GIM_CheckIsSameOperandIgnoreCopies"
1151*0fca6ea1SDimitry Andric                                   : "GIM_CheckIsSameOperand")
1152*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1153*0fca6ea1SDimitry Andric         << MatchTable::Comment("OpIdx") << MatchTable::ULEB128Value(OpIdx)
1154*0fca6ea1SDimitry Andric         << MatchTable::Comment("OtherMI")
1155*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(OtherInsnVarID)
1156*0fca6ea1SDimitry Andric         << MatchTable::Comment("OtherOpIdx")
1157*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(OtherOM.getOpIdx())
1158*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
1159*0fca6ea1SDimitry Andric }
1160*0fca6ea1SDimitry Andric 
1161*0fca6ea1SDimitry Andric //===- LLTOperandMatcher --------------------------------------------------===//
1162*0fca6ea1SDimitry Andric 
1163*0fca6ea1SDimitry Andric std::map<LLTCodeGen, unsigned> LLTOperandMatcher::TypeIDValues;
1164*0fca6ea1SDimitry Andric 
1165*0fca6ea1SDimitry Andric MatchTableRecord LLTOperandMatcher::getValue() const {
1166*0fca6ea1SDimitry Andric   const auto VI = TypeIDValues.find(Ty);
1167*0fca6ea1SDimitry Andric   if (VI == TypeIDValues.end())
1168*0fca6ea1SDimitry Andric     return MatchTable::NamedValue(1, getTy().getCxxEnumValue());
1169*0fca6ea1SDimitry Andric   return MatchTable::NamedValue(1, getTy().getCxxEnumValue(), VI->second);
1170*0fca6ea1SDimitry Andric }
1171*0fca6ea1SDimitry Andric 
1172*0fca6ea1SDimitry Andric bool LLTOperandMatcher::hasValue() const {
1173*0fca6ea1SDimitry Andric   if (TypeIDValues.size() != KnownTypes.size())
1174*0fca6ea1SDimitry Andric     initTypeIDValuesMap();
1175*0fca6ea1SDimitry Andric   return TypeIDValues.count(Ty);
1176*0fca6ea1SDimitry Andric }
1177*0fca6ea1SDimitry Andric 
1178*0fca6ea1SDimitry Andric void LLTOperandMatcher::emitPredicateOpcodes(MatchTable &Table,
1179*0fca6ea1SDimitry Andric                                              RuleMatcher &Rule) const {
1180*0fca6ea1SDimitry Andric   if (InsnVarID == 0) {
1181*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_RootCheckType");
1182*0fca6ea1SDimitry Andric   } else {
1183*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_CheckType") << MatchTable::Comment("MI")
1184*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(InsnVarID);
1185*0fca6ea1SDimitry Andric   }
1186*0fca6ea1SDimitry Andric   Table << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx)
1187*0fca6ea1SDimitry Andric         << MatchTable::Comment("Type") << getValue() << MatchTable::LineBreak;
1188*0fca6ea1SDimitry Andric }
1189*0fca6ea1SDimitry Andric 
1190*0fca6ea1SDimitry Andric //===- PointerToAnyOperandMatcher -----------------------------------------===//
1191*0fca6ea1SDimitry Andric 
1192*0fca6ea1SDimitry Andric void PointerToAnyOperandMatcher::emitPredicateOpcodes(MatchTable &Table,
1193*0fca6ea1SDimitry Andric                                                       RuleMatcher &Rule) const {
1194*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_CheckPointerToAny")
1195*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1196*0fca6ea1SDimitry Andric         << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx)
1197*0fca6ea1SDimitry Andric         << MatchTable::Comment("SizeInBits")
1198*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(SizeInBits) << MatchTable::LineBreak;
1199*0fca6ea1SDimitry Andric }
1200*0fca6ea1SDimitry Andric 
1201*0fca6ea1SDimitry Andric //===- RecordNamedOperandMatcher ------------------------------------------===//
1202*0fca6ea1SDimitry Andric 
1203*0fca6ea1SDimitry Andric void RecordNamedOperandMatcher::emitPredicateOpcodes(MatchTable &Table,
1204*0fca6ea1SDimitry Andric                                                      RuleMatcher &Rule) const {
1205*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_RecordNamedOperand")
1206*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1207*0fca6ea1SDimitry Andric         << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx)
1208*0fca6ea1SDimitry Andric         << MatchTable::Comment("StoreIdx") << MatchTable::ULEB128Value(StoreIdx)
1209*0fca6ea1SDimitry Andric         << MatchTable::Comment("Name : " + Name) << MatchTable::LineBreak;
1210*0fca6ea1SDimitry Andric }
1211*0fca6ea1SDimitry Andric 
1212*0fca6ea1SDimitry Andric //===- RecordRegisterType ------------------------------------------===//
1213*0fca6ea1SDimitry Andric 
1214*0fca6ea1SDimitry Andric void RecordRegisterType::emitPredicateOpcodes(MatchTable &Table,
1215*0fca6ea1SDimitry Andric                                               RuleMatcher &Rule) const {
1216*0fca6ea1SDimitry Andric   assert(Idx < 0 && "Temp types always have negative indexes!");
1217*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_RecordRegType") << MatchTable::Comment("MI")
1218*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(InsnVarID) << MatchTable::Comment("Op")
1219*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(OpIdx) << MatchTable::Comment("TempTypeIdx")
1220*0fca6ea1SDimitry Andric         << MatchTable::IntValue(1, Idx) << MatchTable::LineBreak;
1221*0fca6ea1SDimitry Andric }
1222*0fca6ea1SDimitry Andric 
1223*0fca6ea1SDimitry Andric //===- ComplexPatternOperandMatcher ---------------------------------------===//
1224*0fca6ea1SDimitry Andric 
1225*0fca6ea1SDimitry Andric void ComplexPatternOperandMatcher::emitPredicateOpcodes(
1226*0fca6ea1SDimitry Andric     MatchTable &Table, RuleMatcher &Rule) const {
1227*0fca6ea1SDimitry Andric   unsigned ID = getAllocatedTemporariesBaseID();
1228*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_CheckComplexPattern")
1229*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1230*0fca6ea1SDimitry Andric         << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx)
1231*0fca6ea1SDimitry Andric         << MatchTable::Comment("Renderer") << MatchTable::IntValue(2, ID)
1232*0fca6ea1SDimitry Andric         << MatchTable::NamedValue(2, ("GICP_" + TheDef.getName()).str())
1233*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
1234*0fca6ea1SDimitry Andric }
1235*0fca6ea1SDimitry Andric 
1236*0fca6ea1SDimitry Andric unsigned ComplexPatternOperandMatcher::getAllocatedTemporariesBaseID() const {
1237*0fca6ea1SDimitry Andric   return Operand.getAllocatedTemporariesBaseID();
1238*0fca6ea1SDimitry Andric }
1239*0fca6ea1SDimitry Andric 
1240*0fca6ea1SDimitry Andric //===- RegisterBankOperandMatcher -----------------------------------------===//
1241*0fca6ea1SDimitry Andric 
1242*0fca6ea1SDimitry Andric bool RegisterBankOperandMatcher::isIdentical(const PredicateMatcher &B) const {
1243*0fca6ea1SDimitry Andric   return OperandPredicateMatcher::isIdentical(B) &&
1244*0fca6ea1SDimitry Andric          RC.getDef() == cast<RegisterBankOperandMatcher>(&B)->RC.getDef();
1245*0fca6ea1SDimitry Andric }
1246*0fca6ea1SDimitry Andric 
1247*0fca6ea1SDimitry Andric void RegisterBankOperandMatcher::emitPredicateOpcodes(MatchTable &Table,
1248*0fca6ea1SDimitry Andric                                                       RuleMatcher &Rule) const {
1249*0fca6ea1SDimitry Andric   if (InsnVarID == 0) {
1250*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_RootCheckRegBankForClass");
1251*0fca6ea1SDimitry Andric   } else {
1252*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_CheckRegBankForClass")
1253*0fca6ea1SDimitry Andric           << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID);
1254*0fca6ea1SDimitry Andric   }
1255*0fca6ea1SDimitry Andric 
1256*0fca6ea1SDimitry Andric   Table << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx)
1257*0fca6ea1SDimitry Andric         << MatchTable::Comment("RC")
1258*0fca6ea1SDimitry Andric         << MatchTable::NamedValue(2, RC.getQualifiedIdName())
1259*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
1260*0fca6ea1SDimitry Andric }
1261*0fca6ea1SDimitry Andric 
1262*0fca6ea1SDimitry Andric //===- MBBOperandMatcher --------------------------------------------------===//
1263*0fca6ea1SDimitry Andric 
1264*0fca6ea1SDimitry Andric void MBBOperandMatcher::emitPredicateOpcodes(MatchTable &Table,
1265*0fca6ea1SDimitry Andric                                              RuleMatcher &Rule) const {
1266*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_CheckIsMBB") << MatchTable::Comment("MI")
1267*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(InsnVarID) << MatchTable::Comment("Op")
1268*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(OpIdx) << MatchTable::LineBreak;
1269*0fca6ea1SDimitry Andric }
1270*0fca6ea1SDimitry Andric 
1271*0fca6ea1SDimitry Andric //===- ImmOperandMatcher --------------------------------------------------===//
1272*0fca6ea1SDimitry Andric 
1273*0fca6ea1SDimitry Andric void ImmOperandMatcher::emitPredicateOpcodes(MatchTable &Table,
1274*0fca6ea1SDimitry Andric                                              RuleMatcher &Rule) const {
1275*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_CheckIsImm") << MatchTable::Comment("MI")
1276*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(InsnVarID) << MatchTable::Comment("Op")
1277*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(OpIdx) << MatchTable::LineBreak;
1278*0fca6ea1SDimitry Andric }
1279*0fca6ea1SDimitry Andric 
1280*0fca6ea1SDimitry Andric //===- ConstantIntOperandMatcher ------------------------------------------===//
1281*0fca6ea1SDimitry Andric 
1282*0fca6ea1SDimitry Andric void ConstantIntOperandMatcher::emitPredicateOpcodes(MatchTable &Table,
1283*0fca6ea1SDimitry Andric                                                      RuleMatcher &Rule) const {
1284*0fca6ea1SDimitry Andric   const bool IsInt8 = isInt<8>(Value);
1285*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode(IsInt8 ? "GIM_CheckConstantInt8"
1286*0fca6ea1SDimitry Andric                                      : "GIM_CheckConstantInt")
1287*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1288*0fca6ea1SDimitry Andric         << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx)
1289*0fca6ea1SDimitry Andric         << MatchTable::IntValue(IsInt8 ? 1 : 8, Value) << MatchTable::LineBreak;
1290*0fca6ea1SDimitry Andric }
1291*0fca6ea1SDimitry Andric 
1292*0fca6ea1SDimitry Andric //===- LiteralIntOperandMatcher -------------------------------------------===//
1293*0fca6ea1SDimitry Andric 
1294*0fca6ea1SDimitry Andric void LiteralIntOperandMatcher::emitPredicateOpcodes(MatchTable &Table,
1295*0fca6ea1SDimitry Andric                                                     RuleMatcher &Rule) const {
1296*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_CheckLiteralInt")
1297*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1298*0fca6ea1SDimitry Andric         << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx)
1299*0fca6ea1SDimitry Andric         << MatchTable::IntValue(8, Value) << MatchTable::LineBreak;
1300*0fca6ea1SDimitry Andric }
1301*0fca6ea1SDimitry Andric 
1302*0fca6ea1SDimitry Andric //===- CmpPredicateOperandMatcher -----------------------------------------===//
1303*0fca6ea1SDimitry Andric 
1304*0fca6ea1SDimitry Andric void CmpPredicateOperandMatcher::emitPredicateOpcodes(MatchTable &Table,
1305*0fca6ea1SDimitry Andric                                                       RuleMatcher &Rule) const {
1306*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_CheckCmpPredicate")
1307*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1308*0fca6ea1SDimitry Andric         << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx)
1309*0fca6ea1SDimitry Andric         << MatchTable::Comment("Predicate")
1310*0fca6ea1SDimitry Andric         << MatchTable::NamedValue(2, "CmpInst", PredName)
1311*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
1312*0fca6ea1SDimitry Andric }
1313*0fca6ea1SDimitry Andric 
1314*0fca6ea1SDimitry Andric //===- IntrinsicIDOperandMatcher ------------------------------------------===//
1315*0fca6ea1SDimitry Andric 
1316*0fca6ea1SDimitry Andric void IntrinsicIDOperandMatcher::emitPredicateOpcodes(MatchTable &Table,
1317*0fca6ea1SDimitry Andric                                                      RuleMatcher &Rule) const {
1318*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_CheckIntrinsicID")
1319*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1320*0fca6ea1SDimitry Andric         << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx)
1321*0fca6ea1SDimitry Andric         << MatchTable::NamedValue(2, "Intrinsic::" + II->EnumName)
1322*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
1323*0fca6ea1SDimitry Andric }
1324*0fca6ea1SDimitry Andric 
1325*0fca6ea1SDimitry Andric //===- OperandImmPredicateMatcher -----------------------------------------===//
1326*0fca6ea1SDimitry Andric 
1327*0fca6ea1SDimitry Andric void OperandImmPredicateMatcher::emitPredicateOpcodes(MatchTable &Table,
1328*0fca6ea1SDimitry Andric                                                       RuleMatcher &Rule) const {
1329*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_CheckImmOperandPredicate")
1330*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1331*0fca6ea1SDimitry Andric         << MatchTable::Comment("MO") << MatchTable::ULEB128Value(OpIdx)
1332*0fca6ea1SDimitry Andric         << MatchTable::Comment("Predicate")
1333*0fca6ea1SDimitry Andric         << MatchTable::NamedValue(2, getEnumNameForPredicate(Predicate))
1334*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
1335*0fca6ea1SDimitry Andric }
1336*0fca6ea1SDimitry Andric 
1337*0fca6ea1SDimitry Andric //===- OperandMatcher -----------------------------------------------------===//
1338*0fca6ea1SDimitry Andric 
1339*0fca6ea1SDimitry Andric std::string OperandMatcher::getOperandExpr(unsigned InsnVarID) const {
1340*0fca6ea1SDimitry Andric   return "State.MIs[" + llvm::to_string(InsnVarID) + "]->getOperand(" +
1341*0fca6ea1SDimitry Andric          llvm::to_string(OpIdx) + ")";
1342*0fca6ea1SDimitry Andric }
1343*0fca6ea1SDimitry Andric 
1344*0fca6ea1SDimitry Andric unsigned OperandMatcher::getInsnVarID() const { return Insn.getInsnVarID(); }
1345*0fca6ea1SDimitry Andric 
1346*0fca6ea1SDimitry Andric TempTypeIdx OperandMatcher::getTempTypeIdx(RuleMatcher &Rule) {
1347*0fca6ea1SDimitry Andric   if (TTIdx >= 0) {
1348*0fca6ea1SDimitry Andric     // Temp type index not assigned yet, so assign one and add the necessary
1349*0fca6ea1SDimitry Andric     // predicate.
1350*0fca6ea1SDimitry Andric     TTIdx = Rule.getNextTempTypeIdx();
1351*0fca6ea1SDimitry Andric     assert(TTIdx < 0);
1352*0fca6ea1SDimitry Andric     addPredicate<RecordRegisterType>(TTIdx);
1353*0fca6ea1SDimitry Andric     return TTIdx;
1354*0fca6ea1SDimitry Andric   }
1355*0fca6ea1SDimitry Andric   return TTIdx;
1356*0fca6ea1SDimitry Andric }
1357*0fca6ea1SDimitry Andric 
1358*0fca6ea1SDimitry Andric void OperandMatcher::emitPredicateOpcodes(MatchTable &Table,
1359*0fca6ea1SDimitry Andric                                           RuleMatcher &Rule) {
1360*0fca6ea1SDimitry Andric   if (!Optimized) {
1361*0fca6ea1SDimitry Andric     std::string Comment;
1362*0fca6ea1SDimitry Andric     raw_string_ostream CommentOS(Comment);
1363*0fca6ea1SDimitry Andric     CommentOS << "MIs[" << getInsnVarID() << "] ";
1364*0fca6ea1SDimitry Andric     if (SymbolicName.empty())
1365*0fca6ea1SDimitry Andric       CommentOS << "Operand " << OpIdx;
1366*0fca6ea1SDimitry Andric     else
1367*0fca6ea1SDimitry Andric       CommentOS << SymbolicName;
1368*0fca6ea1SDimitry Andric     Table << MatchTable::Comment(Comment) << MatchTable::LineBreak;
1369*0fca6ea1SDimitry Andric   }
1370*0fca6ea1SDimitry Andric 
1371*0fca6ea1SDimitry Andric   emitPredicateListOpcodes(Table, Rule);
1372*0fca6ea1SDimitry Andric }
1373*0fca6ea1SDimitry Andric 
1374*0fca6ea1SDimitry Andric bool OperandMatcher::isHigherPriorityThan(OperandMatcher &B) {
1375*0fca6ea1SDimitry Andric   // Operand matchers involving more predicates have higher priority.
1376*0fca6ea1SDimitry Andric   if (predicates_size() > B.predicates_size())
1377*0fca6ea1SDimitry Andric     return true;
1378*0fca6ea1SDimitry Andric   if (predicates_size() < B.predicates_size())
1379*0fca6ea1SDimitry Andric     return false;
1380*0fca6ea1SDimitry Andric 
1381*0fca6ea1SDimitry Andric   // This assumes that predicates are added in a consistent order.
1382*0fca6ea1SDimitry Andric   for (auto &&Predicate : zip(predicates(), B.predicates())) {
1383*0fca6ea1SDimitry Andric     if (std::get<0>(Predicate)->isHigherPriorityThan(*std::get<1>(Predicate)))
1384*0fca6ea1SDimitry Andric       return true;
1385*0fca6ea1SDimitry Andric     if (std::get<1>(Predicate)->isHigherPriorityThan(*std::get<0>(Predicate)))
1386*0fca6ea1SDimitry Andric       return false;
1387*0fca6ea1SDimitry Andric   }
1388*0fca6ea1SDimitry Andric 
1389*0fca6ea1SDimitry Andric   return false;
1390*0fca6ea1SDimitry Andric }
1391*0fca6ea1SDimitry Andric 
1392*0fca6ea1SDimitry Andric unsigned OperandMatcher::countRendererFns() {
1393*0fca6ea1SDimitry Andric   return std::accumulate(
1394*0fca6ea1SDimitry Andric       predicates().begin(), predicates().end(), 0,
1395*0fca6ea1SDimitry Andric       [](unsigned A,
1396*0fca6ea1SDimitry Andric          const std::unique_ptr<OperandPredicateMatcher> &Predicate) {
1397*0fca6ea1SDimitry Andric         return A + Predicate->countRendererFns();
1398*0fca6ea1SDimitry Andric       });
1399*0fca6ea1SDimitry Andric }
1400*0fca6ea1SDimitry Andric 
1401*0fca6ea1SDimitry Andric Error OperandMatcher::addTypeCheckPredicate(const TypeSetByHwMode &VTy,
1402*0fca6ea1SDimitry Andric                                             bool OperandIsAPointer) {
1403*0fca6ea1SDimitry Andric   if (!VTy.isMachineValueType())
1404*0fca6ea1SDimitry Andric     return failUnsupported("unsupported typeset");
1405*0fca6ea1SDimitry Andric 
1406*0fca6ea1SDimitry Andric   if (VTy.getMachineValueType() == MVT::iPTR && OperandIsAPointer) {
1407*0fca6ea1SDimitry Andric     addPredicate<PointerToAnyOperandMatcher>(0);
1408*0fca6ea1SDimitry Andric     return Error::success();
1409*0fca6ea1SDimitry Andric   }
1410*0fca6ea1SDimitry Andric 
1411*0fca6ea1SDimitry Andric   auto OpTyOrNone = MVTToLLT(VTy.getMachineValueType().SimpleTy);
1412*0fca6ea1SDimitry Andric   if (!OpTyOrNone)
1413*0fca6ea1SDimitry Andric     return failUnsupported("unsupported type");
1414*0fca6ea1SDimitry Andric 
1415*0fca6ea1SDimitry Andric   if (OperandIsAPointer)
1416*0fca6ea1SDimitry Andric     addPredicate<PointerToAnyOperandMatcher>(OpTyOrNone->get().getSizeInBits());
1417*0fca6ea1SDimitry Andric   else if (VTy.isPointer())
1418*0fca6ea1SDimitry Andric     addPredicate<LLTOperandMatcher>(
1419*0fca6ea1SDimitry Andric         LLT::pointer(VTy.getPtrAddrSpace(), OpTyOrNone->get().getSizeInBits()));
1420*0fca6ea1SDimitry Andric   else
1421*0fca6ea1SDimitry Andric     addPredicate<LLTOperandMatcher>(*OpTyOrNone);
1422*0fca6ea1SDimitry Andric   return Error::success();
1423*0fca6ea1SDimitry Andric }
1424*0fca6ea1SDimitry Andric 
1425*0fca6ea1SDimitry Andric //===- InstructionOpcodeMatcher -------------------------------------------===//
1426*0fca6ea1SDimitry Andric 
1427*0fca6ea1SDimitry Andric DenseMap<const CodeGenInstruction *, unsigned>
1428*0fca6ea1SDimitry Andric     InstructionOpcodeMatcher::OpcodeValues;
1429*0fca6ea1SDimitry Andric 
1430*0fca6ea1SDimitry Andric MatchTableRecord
1431*0fca6ea1SDimitry Andric InstructionOpcodeMatcher::getInstValue(const CodeGenInstruction *I) const {
1432*0fca6ea1SDimitry Andric   const auto VI = OpcodeValues.find(I);
1433*0fca6ea1SDimitry Andric   if (VI != OpcodeValues.end())
1434*0fca6ea1SDimitry Andric     return MatchTable::NamedValue(2, I->Namespace, I->TheDef->getName(),
1435*0fca6ea1SDimitry Andric                                   VI->second);
1436*0fca6ea1SDimitry Andric   return MatchTable::NamedValue(2, I->Namespace, I->TheDef->getName());
1437*0fca6ea1SDimitry Andric }
1438*0fca6ea1SDimitry Andric 
1439*0fca6ea1SDimitry Andric void InstructionOpcodeMatcher::initOpcodeValuesMap(
1440*0fca6ea1SDimitry Andric     const CodeGenTarget &Target) {
1441*0fca6ea1SDimitry Andric   OpcodeValues.clear();
1442*0fca6ea1SDimitry Andric 
1443*0fca6ea1SDimitry Andric   for (const CodeGenInstruction *I : Target.getInstructionsByEnumValue())
1444*0fca6ea1SDimitry Andric     OpcodeValues[I] = Target.getInstrIntValue(I->TheDef);
1445*0fca6ea1SDimitry Andric }
1446*0fca6ea1SDimitry Andric 
1447*0fca6ea1SDimitry Andric MatchTableRecord InstructionOpcodeMatcher::getValue() const {
1448*0fca6ea1SDimitry Andric   assert(Insts.size() == 1);
1449*0fca6ea1SDimitry Andric 
1450*0fca6ea1SDimitry Andric   const CodeGenInstruction *I = Insts[0];
1451*0fca6ea1SDimitry Andric   const auto VI = OpcodeValues.find(I);
1452*0fca6ea1SDimitry Andric   if (VI != OpcodeValues.end())
1453*0fca6ea1SDimitry Andric     return MatchTable::NamedValue(2, I->Namespace, I->TheDef->getName(),
1454*0fca6ea1SDimitry Andric                                   VI->second);
1455*0fca6ea1SDimitry Andric   return MatchTable::NamedValue(2, I->Namespace, I->TheDef->getName());
1456*0fca6ea1SDimitry Andric }
1457*0fca6ea1SDimitry Andric 
1458*0fca6ea1SDimitry Andric void InstructionOpcodeMatcher::emitPredicateOpcodes(MatchTable &Table,
1459*0fca6ea1SDimitry Andric                                                     RuleMatcher &Rule) const {
1460*0fca6ea1SDimitry Andric   StringRef CheckType =
1461*0fca6ea1SDimitry Andric       Insts.size() == 1 ? "GIM_CheckOpcode" : "GIM_CheckOpcodeIsEither";
1462*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode(CheckType) << MatchTable::Comment("MI")
1463*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(InsnVarID);
1464*0fca6ea1SDimitry Andric 
1465*0fca6ea1SDimitry Andric   for (const CodeGenInstruction *I : Insts)
1466*0fca6ea1SDimitry Andric     Table << getInstValue(I);
1467*0fca6ea1SDimitry Andric   Table << MatchTable::LineBreak;
1468*0fca6ea1SDimitry Andric }
1469*0fca6ea1SDimitry Andric 
1470*0fca6ea1SDimitry Andric bool InstructionOpcodeMatcher::isHigherPriorityThan(
1471*0fca6ea1SDimitry Andric     const InstructionPredicateMatcher &B) const {
1472*0fca6ea1SDimitry Andric   if (InstructionPredicateMatcher::isHigherPriorityThan(B))
1473*0fca6ea1SDimitry Andric     return true;
1474*0fca6ea1SDimitry Andric   if (B.InstructionPredicateMatcher::isHigherPriorityThan(*this))
1475*0fca6ea1SDimitry Andric     return false;
1476*0fca6ea1SDimitry Andric 
1477*0fca6ea1SDimitry Andric   // Prioritize opcodes for cosmetic reasons in the generated source. Although
1478*0fca6ea1SDimitry Andric   // this is cosmetic at the moment, we may want to drive a similar ordering
1479*0fca6ea1SDimitry Andric   // using instruction frequency information to improve compile time.
1480*0fca6ea1SDimitry Andric   if (const InstructionOpcodeMatcher *BO =
1481*0fca6ea1SDimitry Andric           dyn_cast<InstructionOpcodeMatcher>(&B))
1482*0fca6ea1SDimitry Andric     return Insts[0]->TheDef->getName() < BO->Insts[0]->TheDef->getName();
1483*0fca6ea1SDimitry Andric 
1484*0fca6ea1SDimitry Andric   return false;
1485*0fca6ea1SDimitry Andric }
1486*0fca6ea1SDimitry Andric 
1487*0fca6ea1SDimitry Andric bool InstructionOpcodeMatcher::isConstantInstruction() const {
1488*0fca6ea1SDimitry Andric   return Insts.size() == 1 && Insts[0]->TheDef->getName() == "G_CONSTANT";
1489*0fca6ea1SDimitry Andric }
1490*0fca6ea1SDimitry Andric 
1491*0fca6ea1SDimitry Andric StringRef InstructionOpcodeMatcher::getOpcode() const {
1492*0fca6ea1SDimitry Andric   return Insts[0]->TheDef->getName();
1493*0fca6ea1SDimitry Andric }
1494*0fca6ea1SDimitry Andric 
1495*0fca6ea1SDimitry Andric bool InstructionOpcodeMatcher::isVariadicNumOperands() const {
1496*0fca6ea1SDimitry Andric   // If one is variadic, they all should be.
1497*0fca6ea1SDimitry Andric   return Insts[0]->Operands.isVariadic;
1498*0fca6ea1SDimitry Andric }
1499*0fca6ea1SDimitry Andric 
1500*0fca6ea1SDimitry Andric StringRef InstructionOpcodeMatcher::getOperandType(unsigned OpIdx) const {
1501*0fca6ea1SDimitry Andric   // Types expected to be uniform for all alternatives.
1502*0fca6ea1SDimitry Andric   return Insts[0]->Operands[OpIdx].OperandType;
1503*0fca6ea1SDimitry Andric }
1504*0fca6ea1SDimitry Andric 
1505*0fca6ea1SDimitry Andric //===- InstructionNumOperandsMatcher --------------------------------------===//
1506*0fca6ea1SDimitry Andric 
1507*0fca6ea1SDimitry Andric void InstructionNumOperandsMatcher::emitPredicateOpcodes(
1508*0fca6ea1SDimitry Andric     MatchTable &Table, RuleMatcher &Rule) const {
1509*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_CheckNumOperands")
1510*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1511*0fca6ea1SDimitry Andric         << MatchTable::Comment("Expected")
1512*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(NumOperands) << MatchTable::LineBreak;
1513*0fca6ea1SDimitry Andric }
1514*0fca6ea1SDimitry Andric 
1515*0fca6ea1SDimitry Andric //===- InstructionImmPredicateMatcher -------------------------------------===//
1516*0fca6ea1SDimitry Andric 
1517*0fca6ea1SDimitry Andric bool InstructionImmPredicateMatcher::isIdentical(
1518*0fca6ea1SDimitry Andric     const PredicateMatcher &B) const {
1519*0fca6ea1SDimitry Andric   return InstructionPredicateMatcher::isIdentical(B) &&
1520*0fca6ea1SDimitry Andric          Predicate.getOrigPatFragRecord() ==
1521*0fca6ea1SDimitry Andric              cast<InstructionImmPredicateMatcher>(&B)
1522*0fca6ea1SDimitry Andric                  ->Predicate.getOrigPatFragRecord();
1523*0fca6ea1SDimitry Andric }
1524*0fca6ea1SDimitry Andric 
1525*0fca6ea1SDimitry Andric void InstructionImmPredicateMatcher::emitPredicateOpcodes(
1526*0fca6ea1SDimitry Andric     MatchTable &Table, RuleMatcher &Rule) const {
1527*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode(getMatchOpcodeForImmPredicate(Predicate))
1528*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1529*0fca6ea1SDimitry Andric         << MatchTable::Comment("Predicate")
1530*0fca6ea1SDimitry Andric         << MatchTable::NamedValue(2, getEnumNameForPredicate(Predicate))
1531*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
1532*0fca6ea1SDimitry Andric }
1533*0fca6ea1SDimitry Andric 
1534*0fca6ea1SDimitry Andric //===- AtomicOrderingMMOPredicateMatcher ----------------------------------===//
1535*0fca6ea1SDimitry Andric 
1536*0fca6ea1SDimitry Andric bool AtomicOrderingMMOPredicateMatcher::isIdentical(
1537*0fca6ea1SDimitry Andric     const PredicateMatcher &B) const {
1538*0fca6ea1SDimitry Andric   if (!InstructionPredicateMatcher::isIdentical(B))
1539*0fca6ea1SDimitry Andric     return false;
1540*0fca6ea1SDimitry Andric   const auto &R = *cast<AtomicOrderingMMOPredicateMatcher>(&B);
1541*0fca6ea1SDimitry Andric   return Order == R.Order && Comparator == R.Comparator;
1542*0fca6ea1SDimitry Andric }
1543*0fca6ea1SDimitry Andric 
1544*0fca6ea1SDimitry Andric void AtomicOrderingMMOPredicateMatcher::emitPredicateOpcodes(
1545*0fca6ea1SDimitry Andric     MatchTable &Table, RuleMatcher &Rule) const {
1546*0fca6ea1SDimitry Andric   StringRef Opcode = "GIM_CheckAtomicOrdering";
1547*0fca6ea1SDimitry Andric 
1548*0fca6ea1SDimitry Andric   if (Comparator == AO_OrStronger)
1549*0fca6ea1SDimitry Andric     Opcode = "GIM_CheckAtomicOrderingOrStrongerThan";
1550*0fca6ea1SDimitry Andric   if (Comparator == AO_WeakerThan)
1551*0fca6ea1SDimitry Andric     Opcode = "GIM_CheckAtomicOrderingWeakerThan";
1552*0fca6ea1SDimitry Andric 
1553*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode(Opcode) << MatchTable::Comment("MI")
1554*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(InsnVarID) << MatchTable::Comment("Order")
1555*0fca6ea1SDimitry Andric         << MatchTable::NamedValue(1,
1556*0fca6ea1SDimitry Andric                                   ("(uint8_t)AtomicOrdering::" + Order).str())
1557*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
1558*0fca6ea1SDimitry Andric }
1559*0fca6ea1SDimitry Andric 
1560*0fca6ea1SDimitry Andric //===- MemorySizePredicateMatcher -----------------------------------------===//
1561*0fca6ea1SDimitry Andric 
1562*0fca6ea1SDimitry Andric void MemorySizePredicateMatcher::emitPredicateOpcodes(MatchTable &Table,
1563*0fca6ea1SDimitry Andric                                                       RuleMatcher &Rule) const {
1564*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_CheckMemorySizeEqualTo")
1565*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1566*0fca6ea1SDimitry Andric         << MatchTable::Comment("MMO") << MatchTable::ULEB128Value(MMOIdx)
1567*0fca6ea1SDimitry Andric         << MatchTable::Comment("Size") << MatchTable::IntValue(4, Size)
1568*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
1569*0fca6ea1SDimitry Andric }
1570*0fca6ea1SDimitry Andric 
1571*0fca6ea1SDimitry Andric //===- MemoryAddressSpacePredicateMatcher ---------------------------------===//
1572*0fca6ea1SDimitry Andric 
1573*0fca6ea1SDimitry Andric bool MemoryAddressSpacePredicateMatcher::isIdentical(
1574*0fca6ea1SDimitry Andric     const PredicateMatcher &B) const {
1575*0fca6ea1SDimitry Andric   if (!InstructionPredicateMatcher::isIdentical(B))
1576*0fca6ea1SDimitry Andric     return false;
1577*0fca6ea1SDimitry Andric   auto *Other = cast<MemoryAddressSpacePredicateMatcher>(&B);
1578*0fca6ea1SDimitry Andric   return MMOIdx == Other->MMOIdx && AddrSpaces == Other->AddrSpaces;
1579*0fca6ea1SDimitry Andric }
1580*0fca6ea1SDimitry Andric 
1581*0fca6ea1SDimitry Andric void MemoryAddressSpacePredicateMatcher::emitPredicateOpcodes(
1582*0fca6ea1SDimitry Andric     MatchTable &Table, RuleMatcher &Rule) const {
1583*0fca6ea1SDimitry Andric   assert(AddrSpaces.size() < 256);
1584*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_CheckMemoryAddressSpace")
1585*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1586*0fca6ea1SDimitry Andric         << MatchTable::Comment("MMO")
1587*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(MMOIdx)
1588*0fca6ea1SDimitry Andric         // Encode number of address spaces to expect.
1589*0fca6ea1SDimitry Andric         << MatchTable::Comment("NumAddrSpace")
1590*0fca6ea1SDimitry Andric         << MatchTable::IntValue(1, AddrSpaces.size());
1591*0fca6ea1SDimitry Andric   for (unsigned AS : AddrSpaces)
1592*0fca6ea1SDimitry Andric     Table << MatchTable::Comment("AddrSpace") << MatchTable::ULEB128Value(AS);
1593*0fca6ea1SDimitry Andric 
1594*0fca6ea1SDimitry Andric   Table << MatchTable::LineBreak;
1595*0fca6ea1SDimitry Andric }
1596*0fca6ea1SDimitry Andric 
1597*0fca6ea1SDimitry Andric //===- MemoryAlignmentPredicateMatcher ------------------------------------===//
1598*0fca6ea1SDimitry Andric 
1599*0fca6ea1SDimitry Andric bool MemoryAlignmentPredicateMatcher::isIdentical(
1600*0fca6ea1SDimitry Andric     const PredicateMatcher &B) const {
1601*0fca6ea1SDimitry Andric   if (!InstructionPredicateMatcher::isIdentical(B))
1602*0fca6ea1SDimitry Andric     return false;
1603*0fca6ea1SDimitry Andric   auto *Other = cast<MemoryAlignmentPredicateMatcher>(&B);
1604*0fca6ea1SDimitry Andric   return MMOIdx == Other->MMOIdx && MinAlign == Other->MinAlign;
1605*0fca6ea1SDimitry Andric }
1606*0fca6ea1SDimitry Andric 
1607*0fca6ea1SDimitry Andric void MemoryAlignmentPredicateMatcher::emitPredicateOpcodes(
1608*0fca6ea1SDimitry Andric     MatchTable &Table, RuleMatcher &Rule) const {
1609*0fca6ea1SDimitry Andric   // TODO: we could support more, just need to emit the right opcode or switch
1610*0fca6ea1SDimitry Andric   // to log alignment.
1611*0fca6ea1SDimitry Andric   assert(MinAlign < 256);
1612*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_CheckMemoryAlignment")
1613*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1614*0fca6ea1SDimitry Andric         << MatchTable::Comment("MMO") << MatchTable::ULEB128Value(MMOIdx)
1615*0fca6ea1SDimitry Andric         << MatchTable::Comment("MinAlign") << MatchTable::IntValue(1, MinAlign)
1616*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
1617*0fca6ea1SDimitry Andric }
1618*0fca6ea1SDimitry Andric 
1619*0fca6ea1SDimitry Andric //===- MemoryVsLLTSizePredicateMatcher ------------------------------------===//
1620*0fca6ea1SDimitry Andric 
1621*0fca6ea1SDimitry Andric bool MemoryVsLLTSizePredicateMatcher::isIdentical(
1622*0fca6ea1SDimitry Andric     const PredicateMatcher &B) const {
1623*0fca6ea1SDimitry Andric   return InstructionPredicateMatcher::isIdentical(B) &&
1624*0fca6ea1SDimitry Andric          MMOIdx == cast<MemoryVsLLTSizePredicateMatcher>(&B)->MMOIdx &&
1625*0fca6ea1SDimitry Andric          Relation == cast<MemoryVsLLTSizePredicateMatcher>(&B)->Relation &&
1626*0fca6ea1SDimitry Andric          OpIdx == cast<MemoryVsLLTSizePredicateMatcher>(&B)->OpIdx;
1627*0fca6ea1SDimitry Andric }
1628*0fca6ea1SDimitry Andric 
1629*0fca6ea1SDimitry Andric void MemoryVsLLTSizePredicateMatcher::emitPredicateOpcodes(
1630*0fca6ea1SDimitry Andric     MatchTable &Table, RuleMatcher &Rule) const {
1631*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode(
1632*0fca6ea1SDimitry Andric                Relation == EqualTo       ? "GIM_CheckMemorySizeEqualToLLT"
1633*0fca6ea1SDimitry Andric                : Relation == GreaterThan ? "GIM_CheckMemorySizeGreaterThanLLT"
1634*0fca6ea1SDimitry Andric                                          : "GIM_CheckMemorySizeLessThanLLT")
1635*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1636*0fca6ea1SDimitry Andric         << MatchTable::Comment("MMO") << MatchTable::ULEB128Value(MMOIdx)
1637*0fca6ea1SDimitry Andric         << MatchTable::Comment("OpIdx") << MatchTable::ULEB128Value(OpIdx)
1638*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
1639*0fca6ea1SDimitry Andric }
1640*0fca6ea1SDimitry Andric 
1641*0fca6ea1SDimitry Andric //===- VectorSplatImmPredicateMatcher -------------------------------------===//
1642*0fca6ea1SDimitry Andric 
1643*0fca6ea1SDimitry Andric void VectorSplatImmPredicateMatcher::emitPredicateOpcodes(
1644*0fca6ea1SDimitry Andric     MatchTable &Table, RuleMatcher &Rule) const {
1645*0fca6ea1SDimitry Andric   if (Kind == AllOnes)
1646*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_CheckIsBuildVectorAllOnes");
1647*0fca6ea1SDimitry Andric   else
1648*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIM_CheckIsBuildVectorAllZeros");
1649*0fca6ea1SDimitry Andric 
1650*0fca6ea1SDimitry Andric   Table << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID);
1651*0fca6ea1SDimitry Andric   Table << MatchTable::LineBreak;
1652*0fca6ea1SDimitry Andric }
1653*0fca6ea1SDimitry Andric 
1654*0fca6ea1SDimitry Andric //===- GenericInstructionPredicateMatcher ---------------------------------===//
1655*0fca6ea1SDimitry Andric 
1656*0fca6ea1SDimitry Andric GenericInstructionPredicateMatcher::GenericInstructionPredicateMatcher(
1657*0fca6ea1SDimitry Andric     unsigned InsnVarID, TreePredicateFn Predicate)
1658*0fca6ea1SDimitry Andric     : GenericInstructionPredicateMatcher(InsnVarID,
1659*0fca6ea1SDimitry Andric                                          getEnumNameForPredicate(Predicate)) {}
1660*0fca6ea1SDimitry Andric 
1661*0fca6ea1SDimitry Andric bool GenericInstructionPredicateMatcher::isIdentical(
1662*0fca6ea1SDimitry Andric     const PredicateMatcher &B) const {
1663*0fca6ea1SDimitry Andric   return InstructionPredicateMatcher::isIdentical(B) &&
1664*0fca6ea1SDimitry Andric          EnumVal ==
1665*0fca6ea1SDimitry Andric              static_cast<const GenericInstructionPredicateMatcher &>(B).EnumVal;
1666*0fca6ea1SDimitry Andric }
1667*0fca6ea1SDimitry Andric void GenericInstructionPredicateMatcher::emitPredicateOpcodes(
1668*0fca6ea1SDimitry Andric     MatchTable &Table, RuleMatcher &Rule) const {
1669*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_CheckCxxInsnPredicate")
1670*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1671*0fca6ea1SDimitry Andric         << MatchTable::Comment("FnId") << MatchTable::NamedValue(2, EnumVal)
1672*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
1673*0fca6ea1SDimitry Andric }
1674*0fca6ea1SDimitry Andric 
1675*0fca6ea1SDimitry Andric //===- MIFlagsInstructionPredicateMatcher ---------------------------------===//
1676*0fca6ea1SDimitry Andric 
1677*0fca6ea1SDimitry Andric bool MIFlagsInstructionPredicateMatcher::isIdentical(
1678*0fca6ea1SDimitry Andric     const PredicateMatcher &B) const {
1679*0fca6ea1SDimitry Andric   if (!InstructionPredicateMatcher::isIdentical(B))
1680*0fca6ea1SDimitry Andric     return false;
1681*0fca6ea1SDimitry Andric   const auto &Other =
1682*0fca6ea1SDimitry Andric       static_cast<const MIFlagsInstructionPredicateMatcher &>(B);
1683*0fca6ea1SDimitry Andric   return Flags == Other.Flags && CheckNot == Other.CheckNot;
1684*0fca6ea1SDimitry Andric }
1685*0fca6ea1SDimitry Andric 
1686*0fca6ea1SDimitry Andric void MIFlagsInstructionPredicateMatcher::emitPredicateOpcodes(
1687*0fca6ea1SDimitry Andric     MatchTable &Table, RuleMatcher &Rule) const {
1688*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode(CheckNot ? "GIM_MIFlagsNot" : "GIM_MIFlags")
1689*0fca6ea1SDimitry Andric         << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)
1690*0fca6ea1SDimitry Andric         << MatchTable::NamedValue(4, join(Flags, " | "))
1691*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
1692*0fca6ea1SDimitry Andric }
1693*0fca6ea1SDimitry Andric 
1694*0fca6ea1SDimitry Andric //===- InstructionMatcher -------------------------------------------------===//
1695*0fca6ea1SDimitry Andric 
1696*0fca6ea1SDimitry Andric OperandMatcher &
1697*0fca6ea1SDimitry Andric InstructionMatcher::addOperand(unsigned OpIdx, const std::string &SymbolicName,
1698*0fca6ea1SDimitry Andric                                unsigned AllocatedTemporariesBaseID) {
1699*0fca6ea1SDimitry Andric   Operands.emplace_back(new OperandMatcher(*this, OpIdx, SymbolicName,
1700*0fca6ea1SDimitry Andric                                            AllocatedTemporariesBaseID));
1701*0fca6ea1SDimitry Andric   if (!SymbolicName.empty())
1702*0fca6ea1SDimitry Andric     Rule.defineOperand(SymbolicName, *Operands.back());
1703*0fca6ea1SDimitry Andric 
1704*0fca6ea1SDimitry Andric   return *Operands.back();
1705*0fca6ea1SDimitry Andric }
1706*0fca6ea1SDimitry Andric 
1707*0fca6ea1SDimitry Andric OperandMatcher &InstructionMatcher::getOperand(unsigned OpIdx) {
1708*0fca6ea1SDimitry Andric   auto I = llvm::find_if(Operands,
1709*0fca6ea1SDimitry Andric                          [&OpIdx](const std::unique_ptr<OperandMatcher> &X) {
1710*0fca6ea1SDimitry Andric                            return X->getOpIdx() == OpIdx;
1711*0fca6ea1SDimitry Andric                          });
1712*0fca6ea1SDimitry Andric   if (I != Operands.end())
1713*0fca6ea1SDimitry Andric     return **I;
1714*0fca6ea1SDimitry Andric   llvm_unreachable("Failed to lookup operand");
1715*0fca6ea1SDimitry Andric }
1716*0fca6ea1SDimitry Andric 
1717*0fca6ea1SDimitry Andric OperandMatcher &InstructionMatcher::addPhysRegInput(Record *Reg, unsigned OpIdx,
1718*0fca6ea1SDimitry Andric                                                     unsigned TempOpIdx) {
1719*0fca6ea1SDimitry Andric   assert(SymbolicName.empty());
1720*0fca6ea1SDimitry Andric   OperandMatcher *OM = new OperandMatcher(*this, OpIdx, "", TempOpIdx);
1721*0fca6ea1SDimitry Andric   Operands.emplace_back(OM);
1722*0fca6ea1SDimitry Andric   Rule.definePhysRegOperand(Reg, *OM);
1723*0fca6ea1SDimitry Andric   PhysRegInputs.emplace_back(Reg, OpIdx);
1724*0fca6ea1SDimitry Andric   return *OM;
1725*0fca6ea1SDimitry Andric }
1726*0fca6ea1SDimitry Andric 
1727*0fca6ea1SDimitry Andric void InstructionMatcher::emitPredicateOpcodes(MatchTable &Table,
1728*0fca6ea1SDimitry Andric                                               RuleMatcher &Rule) {
1729*0fca6ea1SDimitry Andric   if (NumOperandsCheck)
1730*0fca6ea1SDimitry Andric     InstructionNumOperandsMatcher(InsnVarID, getNumOperands())
1731*0fca6ea1SDimitry Andric         .emitPredicateOpcodes(Table, Rule);
1732*0fca6ea1SDimitry Andric 
1733*0fca6ea1SDimitry Andric   // First emit all instruction level predicates need to be verified before we
1734*0fca6ea1SDimitry Andric   // can verify operands.
1735*0fca6ea1SDimitry Andric   emitFilteredPredicateListOpcodes(
1736*0fca6ea1SDimitry Andric       [](const PredicateMatcher &P) { return !P.dependsOnOperands(); }, Table,
1737*0fca6ea1SDimitry Andric       Rule);
1738*0fca6ea1SDimitry Andric 
1739*0fca6ea1SDimitry Andric   // Emit all operand constraints.
1740*0fca6ea1SDimitry Andric   for (const auto &Operand : Operands)
1741*0fca6ea1SDimitry Andric     Operand->emitPredicateOpcodes(Table, Rule);
1742*0fca6ea1SDimitry Andric 
1743*0fca6ea1SDimitry Andric   // All of the tablegen defined predicates should now be matched. Now emit
1744*0fca6ea1SDimitry Andric   // any custom predicates that rely on all generated checks.
1745*0fca6ea1SDimitry Andric   emitFilteredPredicateListOpcodes(
1746*0fca6ea1SDimitry Andric       [](const PredicateMatcher &P) { return P.dependsOnOperands(); }, Table,
1747*0fca6ea1SDimitry Andric       Rule);
1748*0fca6ea1SDimitry Andric }
1749*0fca6ea1SDimitry Andric 
1750*0fca6ea1SDimitry Andric bool InstructionMatcher::isHigherPriorityThan(InstructionMatcher &B) {
1751*0fca6ea1SDimitry Andric   // Instruction matchers involving more operands have higher priority.
1752*0fca6ea1SDimitry Andric   if (Operands.size() > B.Operands.size())
1753*0fca6ea1SDimitry Andric     return true;
1754*0fca6ea1SDimitry Andric   if (Operands.size() < B.Operands.size())
1755*0fca6ea1SDimitry Andric     return false;
1756*0fca6ea1SDimitry Andric 
1757*0fca6ea1SDimitry Andric   for (auto &&P : zip(predicates(), B.predicates())) {
1758*0fca6ea1SDimitry Andric     auto L = static_cast<InstructionPredicateMatcher *>(std::get<0>(P).get());
1759*0fca6ea1SDimitry Andric     auto R = static_cast<InstructionPredicateMatcher *>(std::get<1>(P).get());
1760*0fca6ea1SDimitry Andric     if (L->isHigherPriorityThan(*R))
1761*0fca6ea1SDimitry Andric       return true;
1762*0fca6ea1SDimitry Andric     if (R->isHigherPriorityThan(*L))
1763*0fca6ea1SDimitry Andric       return false;
1764*0fca6ea1SDimitry Andric   }
1765*0fca6ea1SDimitry Andric 
1766*0fca6ea1SDimitry Andric   for (auto Operand : zip(Operands, B.Operands)) {
1767*0fca6ea1SDimitry Andric     if (std::get<0>(Operand)->isHigherPriorityThan(*std::get<1>(Operand)))
1768*0fca6ea1SDimitry Andric       return true;
1769*0fca6ea1SDimitry Andric     if (std::get<1>(Operand)->isHigherPriorityThan(*std::get<0>(Operand)))
1770*0fca6ea1SDimitry Andric       return false;
1771*0fca6ea1SDimitry Andric   }
1772*0fca6ea1SDimitry Andric 
1773*0fca6ea1SDimitry Andric   return false;
1774*0fca6ea1SDimitry Andric }
1775*0fca6ea1SDimitry Andric 
1776*0fca6ea1SDimitry Andric unsigned InstructionMatcher::countRendererFns() {
1777*0fca6ea1SDimitry Andric   return std::accumulate(
1778*0fca6ea1SDimitry Andric              predicates().begin(), predicates().end(), 0,
1779*0fca6ea1SDimitry Andric              [](unsigned A,
1780*0fca6ea1SDimitry Andric                 const std::unique_ptr<PredicateMatcher> &Predicate) {
1781*0fca6ea1SDimitry Andric                return A + Predicate->countRendererFns();
1782*0fca6ea1SDimitry Andric              }) +
1783*0fca6ea1SDimitry Andric          std::accumulate(
1784*0fca6ea1SDimitry Andric              Operands.begin(), Operands.end(), 0,
1785*0fca6ea1SDimitry Andric              [](unsigned A, const std::unique_ptr<OperandMatcher> &Operand) {
1786*0fca6ea1SDimitry Andric                return A + Operand->countRendererFns();
1787*0fca6ea1SDimitry Andric              });
1788*0fca6ea1SDimitry Andric }
1789*0fca6ea1SDimitry Andric 
1790*0fca6ea1SDimitry Andric void InstructionMatcher::optimize() {
1791*0fca6ea1SDimitry Andric   SmallVector<std::unique_ptr<PredicateMatcher>, 8> Stash;
1792*0fca6ea1SDimitry Andric   const auto &OpcMatcher = getOpcodeMatcher();
1793*0fca6ea1SDimitry Andric 
1794*0fca6ea1SDimitry Andric   Stash.push_back(predicates_pop_front());
1795*0fca6ea1SDimitry Andric   if (Stash.back().get() == &OpcMatcher) {
1796*0fca6ea1SDimitry Andric     if (NumOperandsCheck && OpcMatcher.isVariadicNumOperands() &&
1797*0fca6ea1SDimitry Andric         getNumOperands() != 0)
1798*0fca6ea1SDimitry Andric       Stash.emplace_back(
1799*0fca6ea1SDimitry Andric           new InstructionNumOperandsMatcher(InsnVarID, getNumOperands()));
1800*0fca6ea1SDimitry Andric     NumOperandsCheck = false;
1801*0fca6ea1SDimitry Andric 
1802*0fca6ea1SDimitry Andric     for (auto &OM : Operands)
1803*0fca6ea1SDimitry Andric       for (auto &OP : OM->predicates())
1804*0fca6ea1SDimitry Andric         if (isa<IntrinsicIDOperandMatcher>(OP)) {
1805*0fca6ea1SDimitry Andric           Stash.push_back(std::move(OP));
1806*0fca6ea1SDimitry Andric           OM->eraseNullPredicates();
1807*0fca6ea1SDimitry Andric           break;
1808*0fca6ea1SDimitry Andric         }
1809*0fca6ea1SDimitry Andric   }
1810*0fca6ea1SDimitry Andric 
1811*0fca6ea1SDimitry Andric   if (InsnVarID > 0) {
1812*0fca6ea1SDimitry Andric     assert(!Operands.empty() && "Nested instruction is expected to def a vreg");
1813*0fca6ea1SDimitry Andric     for (auto &OP : Operands[0]->predicates())
1814*0fca6ea1SDimitry Andric       OP.reset();
1815*0fca6ea1SDimitry Andric     Operands[0]->eraseNullPredicates();
1816*0fca6ea1SDimitry Andric   }
1817*0fca6ea1SDimitry Andric   for (auto &OM : Operands) {
1818*0fca6ea1SDimitry Andric     for (auto &OP : OM->predicates())
1819*0fca6ea1SDimitry Andric       if (isa<LLTOperandMatcher>(OP))
1820*0fca6ea1SDimitry Andric         Stash.push_back(std::move(OP));
1821*0fca6ea1SDimitry Andric     OM->eraseNullPredicates();
1822*0fca6ea1SDimitry Andric   }
1823*0fca6ea1SDimitry Andric   while (!Stash.empty())
1824*0fca6ea1SDimitry Andric     prependPredicate(Stash.pop_back_val());
1825*0fca6ea1SDimitry Andric }
1826*0fca6ea1SDimitry Andric 
1827*0fca6ea1SDimitry Andric //===- InstructionOperandMatcher ------------------------------------------===//
1828*0fca6ea1SDimitry Andric 
1829*0fca6ea1SDimitry Andric void InstructionOperandMatcher::emitCaptureOpcodes(MatchTable &Table,
1830*0fca6ea1SDimitry Andric                                                    RuleMatcher &Rule) const {
1831*0fca6ea1SDimitry Andric   const unsigned NewInsnVarID = InsnMatcher->getInsnVarID();
1832*0fca6ea1SDimitry Andric   const bool IgnoreCopies = Flags & GISF_IgnoreCopies;
1833*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode(IgnoreCopies ? "GIM_RecordInsnIgnoreCopies"
1834*0fca6ea1SDimitry Andric                                            : "GIM_RecordInsn")
1835*0fca6ea1SDimitry Andric         << MatchTable::Comment("DefineMI")
1836*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(NewInsnVarID) << MatchTable::Comment("MI")
1837*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(getInsnVarID())
1838*0fca6ea1SDimitry Andric         << MatchTable::Comment("OpIdx") << MatchTable::ULEB128Value(getOpIdx())
1839*0fca6ea1SDimitry Andric         << MatchTable::Comment("MIs[" + llvm::to_string(NewInsnVarID) + "]")
1840*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
1841*0fca6ea1SDimitry Andric }
1842*0fca6ea1SDimitry Andric 
1843*0fca6ea1SDimitry Andric bool InstructionOperandMatcher::isHigherPriorityThan(
1844*0fca6ea1SDimitry Andric     const OperandPredicateMatcher &B) const {
1845*0fca6ea1SDimitry Andric   if (OperandPredicateMatcher::isHigherPriorityThan(B))
1846*0fca6ea1SDimitry Andric     return true;
1847*0fca6ea1SDimitry Andric   if (B.OperandPredicateMatcher::isHigherPriorityThan(*this))
1848*0fca6ea1SDimitry Andric     return false;
1849*0fca6ea1SDimitry Andric 
1850*0fca6ea1SDimitry Andric   if (const InstructionOperandMatcher *BP =
1851*0fca6ea1SDimitry Andric           dyn_cast<InstructionOperandMatcher>(&B))
1852*0fca6ea1SDimitry Andric     if (InsnMatcher->isHigherPriorityThan(*BP->InsnMatcher))
1853*0fca6ea1SDimitry Andric       return true;
1854*0fca6ea1SDimitry Andric   return false;
1855*0fca6ea1SDimitry Andric }
1856*0fca6ea1SDimitry Andric 
1857*0fca6ea1SDimitry Andric //===- OperandRenderer ----------------------------------------------------===//
1858*0fca6ea1SDimitry Andric 
1859*0fca6ea1SDimitry Andric OperandRenderer::~OperandRenderer() {}
1860*0fca6ea1SDimitry Andric 
1861*0fca6ea1SDimitry Andric //===- CopyRenderer -------------------------------------------------------===//
1862*0fca6ea1SDimitry Andric 
1863*0fca6ea1SDimitry Andric void CopyRenderer::emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule,
1864*0fca6ea1SDimitry Andric                                      unsigned NewInsnID, unsigned OldInsnID,
1865*0fca6ea1SDimitry Andric                                      unsigned OpIdx, StringRef Name) {
1866*0fca6ea1SDimitry Andric   if (NewInsnID == 0 && OldInsnID == 0) {
1867*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIR_RootToRootCopy");
1868*0fca6ea1SDimitry Andric   } else {
1869*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIR_Copy") << MatchTable::Comment("NewInsnID")
1870*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(NewInsnID)
1871*0fca6ea1SDimitry Andric           << MatchTable::Comment("OldInsnID")
1872*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(OldInsnID);
1873*0fca6ea1SDimitry Andric   }
1874*0fca6ea1SDimitry Andric 
1875*0fca6ea1SDimitry Andric   Table << MatchTable::Comment("OpIdx") << MatchTable::ULEB128Value(OpIdx)
1876*0fca6ea1SDimitry Andric         << MatchTable::Comment(Name) << MatchTable::LineBreak;
1877*0fca6ea1SDimitry Andric }
1878*0fca6ea1SDimitry Andric 
1879*0fca6ea1SDimitry Andric void CopyRenderer::emitRenderOpcodes(MatchTable &Table,
1880*0fca6ea1SDimitry Andric                                      RuleMatcher &Rule) const {
1881*0fca6ea1SDimitry Andric   const OperandMatcher &Operand = Rule.getOperandMatcher(SymbolicName);
1882*0fca6ea1SDimitry Andric   unsigned OldInsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher());
1883*0fca6ea1SDimitry Andric   emitRenderOpcodes(Table, Rule, NewInsnID, OldInsnVarID, Operand.getOpIdx(),
1884*0fca6ea1SDimitry Andric                     SymbolicName);
1885*0fca6ea1SDimitry Andric }
1886*0fca6ea1SDimitry Andric 
1887*0fca6ea1SDimitry Andric //===- CopyPhysRegRenderer ------------------------------------------------===//
1888*0fca6ea1SDimitry Andric 
1889*0fca6ea1SDimitry Andric void CopyPhysRegRenderer::emitRenderOpcodes(MatchTable &Table,
1890*0fca6ea1SDimitry Andric                                             RuleMatcher &Rule) const {
1891*0fca6ea1SDimitry Andric   const OperandMatcher &Operand = Rule.getPhysRegOperandMatcher(PhysReg);
1892*0fca6ea1SDimitry Andric   unsigned OldInsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher());
1893*0fca6ea1SDimitry Andric   CopyRenderer::emitRenderOpcodes(Table, Rule, NewInsnID, OldInsnVarID,
1894*0fca6ea1SDimitry Andric                                   Operand.getOpIdx(), PhysReg->getName());
1895*0fca6ea1SDimitry Andric }
1896*0fca6ea1SDimitry Andric 
1897*0fca6ea1SDimitry Andric //===- CopyOrAddZeroRegRenderer -------------------------------------------===//
1898*0fca6ea1SDimitry Andric 
1899*0fca6ea1SDimitry Andric void CopyOrAddZeroRegRenderer::emitRenderOpcodes(MatchTable &Table,
1900*0fca6ea1SDimitry Andric                                                  RuleMatcher &Rule) const {
1901*0fca6ea1SDimitry Andric   const OperandMatcher &Operand = Rule.getOperandMatcher(SymbolicName);
1902*0fca6ea1SDimitry Andric   unsigned OldInsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher());
1903*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIR_CopyOrAddZeroReg")
1904*0fca6ea1SDimitry Andric         << MatchTable::Comment("NewInsnID")
1905*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(NewInsnID)
1906*0fca6ea1SDimitry Andric         << MatchTable::Comment("OldInsnID")
1907*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(OldInsnVarID)
1908*0fca6ea1SDimitry Andric         << MatchTable::Comment("OpIdx")
1909*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(Operand.getOpIdx())
1910*0fca6ea1SDimitry Andric         << MatchTable::NamedValue(
1911*0fca6ea1SDimitry Andric                2,
1912*0fca6ea1SDimitry Andric                (ZeroRegisterDef->getValue("Namespace")
1913*0fca6ea1SDimitry Andric                     ? ZeroRegisterDef->getValueAsString("Namespace")
1914*0fca6ea1SDimitry Andric                     : ""),
1915*0fca6ea1SDimitry Andric                ZeroRegisterDef->getName())
1916*0fca6ea1SDimitry Andric         << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak;
1917*0fca6ea1SDimitry Andric }
1918*0fca6ea1SDimitry Andric 
1919*0fca6ea1SDimitry Andric //===- CopyConstantAsImmRenderer ------------------------------------------===//
1920*0fca6ea1SDimitry Andric 
1921*0fca6ea1SDimitry Andric void CopyConstantAsImmRenderer::emitRenderOpcodes(MatchTable &Table,
1922*0fca6ea1SDimitry Andric                                                   RuleMatcher &Rule) const {
1923*0fca6ea1SDimitry Andric   InstructionMatcher &InsnMatcher = Rule.getInstructionMatcher(SymbolicName);
1924*0fca6ea1SDimitry Andric   unsigned OldInsnVarID = Rule.getInsnVarID(InsnMatcher);
1925*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode(Signed ? "GIR_CopyConstantAsSImm"
1926*0fca6ea1SDimitry Andric                                      : "GIR_CopyConstantAsUImm")
1927*0fca6ea1SDimitry Andric         << MatchTable::Comment("NewInsnID")
1928*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(NewInsnID)
1929*0fca6ea1SDimitry Andric         << MatchTable::Comment("OldInsnID")
1930*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(OldInsnVarID)
1931*0fca6ea1SDimitry Andric         << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak;
1932*0fca6ea1SDimitry Andric }
1933*0fca6ea1SDimitry Andric 
1934*0fca6ea1SDimitry Andric //===- CopyFConstantAsFPImmRenderer ---------------------------------------===//
1935*0fca6ea1SDimitry Andric 
1936*0fca6ea1SDimitry Andric void CopyFConstantAsFPImmRenderer::emitRenderOpcodes(MatchTable &Table,
1937*0fca6ea1SDimitry Andric                                                      RuleMatcher &Rule) const {
1938*0fca6ea1SDimitry Andric   InstructionMatcher &InsnMatcher = Rule.getInstructionMatcher(SymbolicName);
1939*0fca6ea1SDimitry Andric   unsigned OldInsnVarID = Rule.getInsnVarID(InsnMatcher);
1940*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIR_CopyFConstantAsFPImm")
1941*0fca6ea1SDimitry Andric         << MatchTable::Comment("NewInsnID")
1942*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(NewInsnID)
1943*0fca6ea1SDimitry Andric         << MatchTable::Comment("OldInsnID")
1944*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(OldInsnVarID)
1945*0fca6ea1SDimitry Andric         << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak;
1946*0fca6ea1SDimitry Andric }
1947*0fca6ea1SDimitry Andric 
1948*0fca6ea1SDimitry Andric //===- CopySubRegRenderer -------------------------------------------------===//
1949*0fca6ea1SDimitry Andric 
1950*0fca6ea1SDimitry Andric void CopySubRegRenderer::emitRenderOpcodes(MatchTable &Table,
1951*0fca6ea1SDimitry Andric                                            RuleMatcher &Rule) const {
1952*0fca6ea1SDimitry Andric   const OperandMatcher &Operand = Rule.getOperandMatcher(SymbolicName);
1953*0fca6ea1SDimitry Andric   unsigned OldInsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher());
1954*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIR_CopySubReg")
1955*0fca6ea1SDimitry Andric         << MatchTable::Comment("NewInsnID")
1956*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(NewInsnID)
1957*0fca6ea1SDimitry Andric         << MatchTable::Comment("OldInsnID")
1958*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(OldInsnVarID)
1959*0fca6ea1SDimitry Andric         << MatchTable::Comment("OpIdx")
1960*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(Operand.getOpIdx())
1961*0fca6ea1SDimitry Andric         << MatchTable::Comment("SubRegIdx")
1962*0fca6ea1SDimitry Andric         << MatchTable::IntValue(2, SubReg->EnumValue)
1963*0fca6ea1SDimitry Andric         << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak;
1964*0fca6ea1SDimitry Andric }
1965*0fca6ea1SDimitry Andric 
1966*0fca6ea1SDimitry Andric //===- AddRegisterRenderer ------------------------------------------------===//
1967*0fca6ea1SDimitry Andric 
1968*0fca6ea1SDimitry Andric void AddRegisterRenderer::emitRenderOpcodes(MatchTable &Table,
1969*0fca6ea1SDimitry Andric                                             RuleMatcher &Rule) const {
1970*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIR_AddRegister")
1971*0fca6ea1SDimitry Andric         << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID);
1972*0fca6ea1SDimitry Andric   if (RegisterDef->getName() != "zero_reg") {
1973*0fca6ea1SDimitry Andric     Table << MatchTable::NamedValue(
1974*0fca6ea1SDimitry Andric         2,
1975*0fca6ea1SDimitry Andric         (RegisterDef->getValue("Namespace")
1976*0fca6ea1SDimitry Andric              ? RegisterDef->getValueAsString("Namespace")
1977*0fca6ea1SDimitry Andric              : ""),
1978*0fca6ea1SDimitry Andric         RegisterDef->getName());
1979*0fca6ea1SDimitry Andric   } else {
1980*0fca6ea1SDimitry Andric     Table << MatchTable::NamedValue(2, Target.getRegNamespace(), "NoRegister");
1981*0fca6ea1SDimitry Andric   }
1982*0fca6ea1SDimitry Andric   Table << MatchTable::Comment("AddRegisterRegFlags");
1983*0fca6ea1SDimitry Andric 
1984*0fca6ea1SDimitry Andric   // TODO: This is encoded as a 64-bit element, but only 16 or 32-bits are
1985*0fca6ea1SDimitry Andric   // really needed for a physical register reference. We can pack the
1986*0fca6ea1SDimitry Andric   // register and flags in a single field.
1987*0fca6ea1SDimitry Andric   if (IsDef)
1988*0fca6ea1SDimitry Andric     Table << MatchTable::NamedValue(2, "RegState::Define");
1989*0fca6ea1SDimitry Andric   else
1990*0fca6ea1SDimitry Andric     Table << MatchTable::IntValue(2, 0);
1991*0fca6ea1SDimitry Andric   Table << MatchTable::LineBreak;
1992*0fca6ea1SDimitry Andric }
1993*0fca6ea1SDimitry Andric 
1994*0fca6ea1SDimitry Andric //===- TempRegRenderer ----------------------------------------------------===//
1995*0fca6ea1SDimitry Andric 
1996*0fca6ea1SDimitry Andric void TempRegRenderer::emitRenderOpcodes(MatchTable &Table,
1997*0fca6ea1SDimitry Andric                                         RuleMatcher &Rule) const {
1998*0fca6ea1SDimitry Andric   const bool NeedsFlags = (SubRegIdx || IsDef);
1999*0fca6ea1SDimitry Andric   if (SubRegIdx) {
2000*0fca6ea1SDimitry Andric     assert(!IsDef);
2001*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIR_AddTempSubRegister");
2002*0fca6ea1SDimitry Andric   } else
2003*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode(NeedsFlags ? "GIR_AddTempRegister"
2004*0fca6ea1SDimitry Andric                                            : "GIR_AddSimpleTempRegister");
2005*0fca6ea1SDimitry Andric 
2006*0fca6ea1SDimitry Andric   Table << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
2007*0fca6ea1SDimitry Andric         << MatchTable::Comment("TempRegID")
2008*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(TempRegID);
2009*0fca6ea1SDimitry Andric 
2010*0fca6ea1SDimitry Andric   if (!NeedsFlags) {
2011*0fca6ea1SDimitry Andric     Table << MatchTable::LineBreak;
2012*0fca6ea1SDimitry Andric     return;
2013*0fca6ea1SDimitry Andric   }
2014*0fca6ea1SDimitry Andric 
2015*0fca6ea1SDimitry Andric   Table << MatchTable::Comment("TempRegFlags");
2016*0fca6ea1SDimitry Andric   if (IsDef) {
2017*0fca6ea1SDimitry Andric     SmallString<32> RegFlags;
2018*0fca6ea1SDimitry Andric     RegFlags += "RegState::Define";
2019*0fca6ea1SDimitry Andric     if (IsDead)
2020*0fca6ea1SDimitry Andric       RegFlags += "|RegState::Dead";
2021*0fca6ea1SDimitry Andric     Table << MatchTable::NamedValue(2, RegFlags);
2022*0fca6ea1SDimitry Andric   } else
2023*0fca6ea1SDimitry Andric     Table << MatchTable::IntValue(2, 0);
2024*0fca6ea1SDimitry Andric 
2025*0fca6ea1SDimitry Andric   if (SubRegIdx)
2026*0fca6ea1SDimitry Andric     Table << MatchTable::NamedValue(2, SubRegIdx->getQualifiedName());
2027*0fca6ea1SDimitry Andric   Table << MatchTable::LineBreak;
2028*0fca6ea1SDimitry Andric }
2029*0fca6ea1SDimitry Andric 
2030*0fca6ea1SDimitry Andric //===- ImmRenderer --------------------------------------------------------===//
2031*0fca6ea1SDimitry Andric 
2032*0fca6ea1SDimitry Andric void ImmRenderer::emitAddImm(MatchTable &Table, RuleMatcher &RM,
2033*0fca6ea1SDimitry Andric                              unsigned InsnID, int64_t Imm, StringRef ImmName) {
2034*0fca6ea1SDimitry Andric   const bool IsInt8 = isInt<8>(Imm);
2035*0fca6ea1SDimitry Andric 
2036*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode(IsInt8 ? "GIR_AddImm8" : "GIR_AddImm")
2037*0fca6ea1SDimitry Andric         << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
2038*0fca6ea1SDimitry Andric         << MatchTable::Comment(ImmName)
2039*0fca6ea1SDimitry Andric         << MatchTable::IntValue(IsInt8 ? 1 : 8, Imm) << MatchTable::LineBreak;
2040*0fca6ea1SDimitry Andric }
2041*0fca6ea1SDimitry Andric 
2042*0fca6ea1SDimitry Andric void ImmRenderer::emitRenderOpcodes(MatchTable &Table,
2043*0fca6ea1SDimitry Andric                                     RuleMatcher &Rule) const {
2044*0fca6ea1SDimitry Andric   if (CImmLLT) {
2045*0fca6ea1SDimitry Andric     assert(Table.isCombiner() &&
2046*0fca6ea1SDimitry Andric            "ConstantInt immediate are only for combiners!");
2047*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIR_AddCImm") << MatchTable::Comment("InsnID")
2048*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(InsnID) << MatchTable::Comment("Type")
2049*0fca6ea1SDimitry Andric           << *CImmLLT << MatchTable::Comment("Imm")
2050*0fca6ea1SDimitry Andric           << MatchTable::IntValue(8, Imm) << MatchTable::LineBreak;
2051*0fca6ea1SDimitry Andric   } else
2052*0fca6ea1SDimitry Andric     emitAddImm(Table, Rule, InsnID, Imm);
2053*0fca6ea1SDimitry Andric }
2054*0fca6ea1SDimitry Andric 
2055*0fca6ea1SDimitry Andric //===- SubRegIndexRenderer ------------------------------------------------===//
2056*0fca6ea1SDimitry Andric 
2057*0fca6ea1SDimitry Andric void SubRegIndexRenderer::emitRenderOpcodes(MatchTable &Table,
2058*0fca6ea1SDimitry Andric                                             RuleMatcher &Rule) const {
2059*0fca6ea1SDimitry Andric   ImmRenderer::emitAddImm(Table, Rule, InsnID, SubRegIdx->EnumValue,
2060*0fca6ea1SDimitry Andric                           "SubRegIndex");
2061*0fca6ea1SDimitry Andric }
2062*0fca6ea1SDimitry Andric 
2063*0fca6ea1SDimitry Andric //===- RenderComplexPatternOperand ----------------------------------------===//
2064*0fca6ea1SDimitry Andric 
2065*0fca6ea1SDimitry Andric void RenderComplexPatternOperand::emitRenderOpcodes(MatchTable &Table,
2066*0fca6ea1SDimitry Andric                                                     RuleMatcher &Rule) const {
2067*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode(
2068*0fca6ea1SDimitry Andric                SubOperand ? (SubReg ? "GIR_ComplexSubOperandSubRegRenderer"
2069*0fca6ea1SDimitry Andric                                     : "GIR_ComplexSubOperandRenderer")
2070*0fca6ea1SDimitry Andric                           : "GIR_ComplexRenderer")
2071*0fca6ea1SDimitry Andric         << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
2072*0fca6ea1SDimitry Andric         << MatchTable::Comment("RendererID")
2073*0fca6ea1SDimitry Andric         << MatchTable::IntValue(2, RendererID);
2074*0fca6ea1SDimitry Andric   if (SubOperand)
2075*0fca6ea1SDimitry Andric     Table << MatchTable::Comment("SubOperand")
2076*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(*SubOperand);
2077*0fca6ea1SDimitry Andric   if (SubReg)
2078*0fca6ea1SDimitry Andric     Table << MatchTable::Comment("SubRegIdx")
2079*0fca6ea1SDimitry Andric           << MatchTable::IntValue(2, SubReg->EnumValue);
2080*0fca6ea1SDimitry Andric   Table << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak;
2081*0fca6ea1SDimitry Andric }
2082*0fca6ea1SDimitry Andric 
2083*0fca6ea1SDimitry Andric //===- IntrinsicIDRenderer ------------------------------------------------===//
2084*0fca6ea1SDimitry Andric 
2085*0fca6ea1SDimitry Andric void IntrinsicIDRenderer::emitRenderOpcodes(MatchTable &Table,
2086*0fca6ea1SDimitry Andric                                             RuleMatcher &Rule) const {
2087*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIR_AddIntrinsicID") << MatchTable::Comment("MI")
2088*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(InsnID)
2089*0fca6ea1SDimitry Andric         << MatchTable::NamedValue(2, "Intrinsic::" + II->EnumName)
2090*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
2091*0fca6ea1SDimitry Andric }
2092*0fca6ea1SDimitry Andric 
2093*0fca6ea1SDimitry Andric //===- CustomRenderer -----------------------------------------------------===//
2094*0fca6ea1SDimitry Andric 
2095*0fca6ea1SDimitry Andric void CustomRenderer::emitRenderOpcodes(MatchTable &Table,
2096*0fca6ea1SDimitry Andric                                        RuleMatcher &Rule) const {
2097*0fca6ea1SDimitry Andric   InstructionMatcher &InsnMatcher = Rule.getInstructionMatcher(SymbolicName);
2098*0fca6ea1SDimitry Andric   unsigned OldInsnVarID = Rule.getInsnVarID(InsnMatcher);
2099*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIR_CustomRenderer")
2100*0fca6ea1SDimitry Andric         << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
2101*0fca6ea1SDimitry Andric         << MatchTable::Comment("OldInsnID")
2102*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(OldInsnVarID)
2103*0fca6ea1SDimitry Andric         << MatchTable::Comment("Renderer")
2104*0fca6ea1SDimitry Andric         << MatchTable::NamedValue(
2105*0fca6ea1SDimitry Andric                2, "GICR_" + Renderer.getValueAsString("RendererFn").str())
2106*0fca6ea1SDimitry Andric         << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak;
2107*0fca6ea1SDimitry Andric }
2108*0fca6ea1SDimitry Andric 
2109*0fca6ea1SDimitry Andric //===- CustomOperandRenderer ----------------------------------------------===//
2110*0fca6ea1SDimitry Andric 
2111*0fca6ea1SDimitry Andric void CustomOperandRenderer::emitRenderOpcodes(MatchTable &Table,
2112*0fca6ea1SDimitry Andric                                               RuleMatcher &Rule) const {
2113*0fca6ea1SDimitry Andric   const OperandMatcher &OpdMatcher = Rule.getOperandMatcher(SymbolicName);
2114*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIR_CustomOperandRenderer")
2115*0fca6ea1SDimitry Andric         << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
2116*0fca6ea1SDimitry Andric         << MatchTable::Comment("OldInsnID")
2117*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(OpdMatcher.getInsnVarID())
2118*0fca6ea1SDimitry Andric         << MatchTable::Comment("OpIdx")
2119*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(OpdMatcher.getOpIdx())
2120*0fca6ea1SDimitry Andric         << MatchTable::Comment("OperandRenderer")
2121*0fca6ea1SDimitry Andric         << MatchTable::NamedValue(
2122*0fca6ea1SDimitry Andric                2, "GICR_" + Renderer.getValueAsString("RendererFn").str())
2123*0fca6ea1SDimitry Andric         << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak;
2124*0fca6ea1SDimitry Andric }
2125*0fca6ea1SDimitry Andric 
2126*0fca6ea1SDimitry Andric //===- BuildMIAction ------------------------------------------------------===//
2127*0fca6ea1SDimitry Andric 
2128*0fca6ea1SDimitry Andric bool BuildMIAction::canMutate(RuleMatcher &Rule,
2129*0fca6ea1SDimitry Andric                               const InstructionMatcher *Insn) const {
2130*0fca6ea1SDimitry Andric   if (!Insn)
2131*0fca6ea1SDimitry Andric     return false;
2132*0fca6ea1SDimitry Andric 
2133*0fca6ea1SDimitry Andric   if (OperandRenderers.size() != Insn->getNumOperands())
2134*0fca6ea1SDimitry Andric     return false;
2135*0fca6ea1SDimitry Andric 
2136*0fca6ea1SDimitry Andric   for (const auto &Renderer : enumerate(OperandRenderers)) {
2137*0fca6ea1SDimitry Andric     if (const auto *Copy = dyn_cast<CopyRenderer>(&*Renderer.value())) {
2138*0fca6ea1SDimitry Andric       const OperandMatcher &OM =
2139*0fca6ea1SDimitry Andric           Rule.getOperandMatcher(Copy->getSymbolicName());
2140*0fca6ea1SDimitry Andric       if (Insn != &OM.getInstructionMatcher() ||
2141*0fca6ea1SDimitry Andric           OM.getOpIdx() != Renderer.index())
2142*0fca6ea1SDimitry Andric         return false;
2143*0fca6ea1SDimitry Andric     } else
2144*0fca6ea1SDimitry Andric       return false;
2145*0fca6ea1SDimitry Andric   }
2146*0fca6ea1SDimitry Andric 
2147*0fca6ea1SDimitry Andric   return true;
2148*0fca6ea1SDimitry Andric }
2149*0fca6ea1SDimitry Andric 
2150*0fca6ea1SDimitry Andric void BuildMIAction::chooseInsnToMutate(RuleMatcher &Rule) {
2151*0fca6ea1SDimitry Andric   for (auto *MutateCandidate : Rule.mutatable_insns()) {
2152*0fca6ea1SDimitry Andric     if (canMutate(Rule, MutateCandidate)) {
2153*0fca6ea1SDimitry Andric       // Take the first one we're offered that we're able to mutate.
2154*0fca6ea1SDimitry Andric       Rule.reserveInsnMatcherForMutation(MutateCandidate);
2155*0fca6ea1SDimitry Andric       Matched = MutateCandidate;
2156*0fca6ea1SDimitry Andric       return;
2157*0fca6ea1SDimitry Andric     }
2158*0fca6ea1SDimitry Andric   }
2159*0fca6ea1SDimitry Andric }
2160*0fca6ea1SDimitry Andric 
2161*0fca6ea1SDimitry Andric void BuildMIAction::emitActionOpcodes(MatchTable &Table,
2162*0fca6ea1SDimitry Andric                                       RuleMatcher &Rule) const {
2163*0fca6ea1SDimitry Andric   const auto AddMIFlags = [&]() {
2164*0fca6ea1SDimitry Andric     for (const InstructionMatcher *IM : CopiedFlags) {
2165*0fca6ea1SDimitry Andric       Table << MatchTable::Opcode("GIR_CopyMIFlags")
2166*0fca6ea1SDimitry Andric             << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
2167*0fca6ea1SDimitry Andric             << MatchTable::Comment("OldInsnID")
2168*0fca6ea1SDimitry Andric             << MatchTable::ULEB128Value(IM->getInsnVarID())
2169*0fca6ea1SDimitry Andric             << MatchTable::LineBreak;
2170*0fca6ea1SDimitry Andric     }
2171*0fca6ea1SDimitry Andric 
2172*0fca6ea1SDimitry Andric     if (!SetFlags.empty()) {
2173*0fca6ea1SDimitry Andric       Table << MatchTable::Opcode("GIR_SetMIFlags")
2174*0fca6ea1SDimitry Andric             << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
2175*0fca6ea1SDimitry Andric             << MatchTable::NamedValue(4, join(SetFlags, " | "))
2176*0fca6ea1SDimitry Andric             << MatchTable::LineBreak;
2177*0fca6ea1SDimitry Andric     }
2178*0fca6ea1SDimitry Andric 
2179*0fca6ea1SDimitry Andric     if (!UnsetFlags.empty()) {
2180*0fca6ea1SDimitry Andric       Table << MatchTable::Opcode("GIR_UnsetMIFlags")
2181*0fca6ea1SDimitry Andric             << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
2182*0fca6ea1SDimitry Andric             << MatchTable::NamedValue(4, join(UnsetFlags, " | "))
2183*0fca6ea1SDimitry Andric             << MatchTable::LineBreak;
2184*0fca6ea1SDimitry Andric     }
2185*0fca6ea1SDimitry Andric   };
2186*0fca6ea1SDimitry Andric 
2187*0fca6ea1SDimitry Andric   if (Matched) {
2188*0fca6ea1SDimitry Andric     assert(canMutate(Rule, Matched) &&
2189*0fca6ea1SDimitry Andric            "Arranged to mutate an insn that isn't mutatable");
2190*0fca6ea1SDimitry Andric 
2191*0fca6ea1SDimitry Andric     unsigned RecycleInsnID = Rule.getInsnVarID(*Matched);
2192*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIR_MutateOpcode")
2193*0fca6ea1SDimitry Andric           << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
2194*0fca6ea1SDimitry Andric           << MatchTable::Comment("RecycleInsnID")
2195*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(RecycleInsnID)
2196*0fca6ea1SDimitry Andric           << MatchTable::Comment("Opcode")
2197*0fca6ea1SDimitry Andric           << MatchTable::NamedValue(2, I->Namespace, I->TheDef->getName())
2198*0fca6ea1SDimitry Andric           << MatchTable::LineBreak;
2199*0fca6ea1SDimitry Andric 
2200*0fca6ea1SDimitry Andric     if (!I->ImplicitDefs.empty() || !I->ImplicitUses.empty()) {
2201*0fca6ea1SDimitry Andric       for (auto *Def : I->ImplicitDefs) {
2202*0fca6ea1SDimitry Andric         auto Namespace = Def->getValue("Namespace")
2203*0fca6ea1SDimitry Andric                              ? Def->getValueAsString("Namespace")
2204*0fca6ea1SDimitry Andric                              : "";
2205*0fca6ea1SDimitry Andric         const bool IsDead = DeadImplicitDefs.contains(Def);
2206*0fca6ea1SDimitry Andric         Table << MatchTable::Opcode("GIR_AddImplicitDef")
2207*0fca6ea1SDimitry Andric               << MatchTable::Comment("InsnID")
2208*0fca6ea1SDimitry Andric               << MatchTable::ULEB128Value(InsnID)
2209*0fca6ea1SDimitry Andric               << MatchTable::NamedValue(2, Namespace, Def->getName())
2210*0fca6ea1SDimitry Andric               << (IsDead ? MatchTable::NamedValue(2, "RegState", "Dead")
2211*0fca6ea1SDimitry Andric                          : MatchTable::IntValue(2, 0))
2212*0fca6ea1SDimitry Andric               << MatchTable::LineBreak;
2213*0fca6ea1SDimitry Andric       }
2214*0fca6ea1SDimitry Andric       for (auto *Use : I->ImplicitUses) {
2215*0fca6ea1SDimitry Andric         auto Namespace = Use->getValue("Namespace")
2216*0fca6ea1SDimitry Andric                              ? Use->getValueAsString("Namespace")
2217*0fca6ea1SDimitry Andric                              : "";
2218*0fca6ea1SDimitry Andric         Table << MatchTable::Opcode("GIR_AddImplicitUse")
2219*0fca6ea1SDimitry Andric               << MatchTable::Comment("InsnID")
2220*0fca6ea1SDimitry Andric               << MatchTable::ULEB128Value(InsnID)
2221*0fca6ea1SDimitry Andric               << MatchTable::NamedValue(2, Namespace, Use->getName())
2222*0fca6ea1SDimitry Andric               << MatchTable::LineBreak;
2223*0fca6ea1SDimitry Andric       }
2224*0fca6ea1SDimitry Andric     }
2225*0fca6ea1SDimitry Andric 
2226*0fca6ea1SDimitry Andric     AddMIFlags();
2227*0fca6ea1SDimitry Andric 
2228*0fca6ea1SDimitry Andric     // Mark the mutated instruction as erased.
2229*0fca6ea1SDimitry Andric     Rule.tryEraseInsnID(RecycleInsnID);
2230*0fca6ea1SDimitry Andric     return;
2231*0fca6ea1SDimitry Andric   }
2232*0fca6ea1SDimitry Andric 
2233*0fca6ea1SDimitry Andric   // TODO: Simple permutation looks like it could be almost as common as
2234*0fca6ea1SDimitry Andric   //       mutation due to commutative operations.
2235*0fca6ea1SDimitry Andric 
2236*0fca6ea1SDimitry Andric   if (InsnID == 0) {
2237*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIR_BuildRootMI");
2238*0fca6ea1SDimitry Andric   } else {
2239*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIR_BuildMI") << MatchTable::Comment("InsnID")
2240*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(InsnID);
2241*0fca6ea1SDimitry Andric   }
2242*0fca6ea1SDimitry Andric 
2243*0fca6ea1SDimitry Andric   Table << MatchTable::Comment("Opcode")
2244*0fca6ea1SDimitry Andric         << MatchTable::NamedValue(2, I->Namespace, I->TheDef->getName())
2245*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
2246*0fca6ea1SDimitry Andric 
2247*0fca6ea1SDimitry Andric   for (const auto &Renderer : OperandRenderers)
2248*0fca6ea1SDimitry Andric     Renderer->emitRenderOpcodes(Table, Rule);
2249*0fca6ea1SDimitry Andric 
2250*0fca6ea1SDimitry Andric   for (auto [OpIdx, Def] : enumerate(I->ImplicitDefs)) {
2251*0fca6ea1SDimitry Andric     auto Namespace =
2252*0fca6ea1SDimitry Andric         Def->getValue("Namespace") ? Def->getValueAsString("Namespace") : "";
2253*0fca6ea1SDimitry Andric     if (DeadImplicitDefs.contains(Def)) {
2254*0fca6ea1SDimitry Andric       Table
2255*0fca6ea1SDimitry Andric           << MatchTable::Opcode("GIR_SetImplicitDefDead")
2256*0fca6ea1SDimitry Andric           << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
2257*0fca6ea1SDimitry Andric           << MatchTable::Comment(
2258*0fca6ea1SDimitry Andric                  ("OpIdx for " + Namespace + "::" + Def->getName() + "").str())
2259*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(OpIdx) << MatchTable::LineBreak;
2260*0fca6ea1SDimitry Andric     }
2261*0fca6ea1SDimitry Andric   }
2262*0fca6ea1SDimitry Andric 
2263*0fca6ea1SDimitry Andric   if (I->mayLoad || I->mayStore) {
2264*0fca6ea1SDimitry Andric     // Emit the ID's for all the instructions that are matched by this rule.
2265*0fca6ea1SDimitry Andric     // TODO: Limit this to matched instructions that mayLoad/mayStore or have
2266*0fca6ea1SDimitry Andric     //       some other means of having a memoperand. Also limit this to
2267*0fca6ea1SDimitry Andric     //       emitted instructions that expect to have a memoperand too. For
2268*0fca6ea1SDimitry Andric     //       example, (G_SEXT (G_LOAD x)) that results in separate load and
2269*0fca6ea1SDimitry Andric     //       sign-extend instructions shouldn't put the memoperand on the
2270*0fca6ea1SDimitry Andric     //       sign-extend since it has no effect there.
2271*0fca6ea1SDimitry Andric 
2272*0fca6ea1SDimitry Andric     std::vector<unsigned> MergeInsnIDs;
2273*0fca6ea1SDimitry Andric     for (const auto &IDMatcherPair : Rule.defined_insn_vars())
2274*0fca6ea1SDimitry Andric       MergeInsnIDs.push_back(IDMatcherPair.second);
2275*0fca6ea1SDimitry Andric     llvm::sort(MergeInsnIDs);
2276*0fca6ea1SDimitry Andric 
2277*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIR_MergeMemOperands")
2278*0fca6ea1SDimitry Andric           << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
2279*0fca6ea1SDimitry Andric           << MatchTable::Comment("NumInsns")
2280*0fca6ea1SDimitry Andric           << MatchTable::IntValue(1, MergeInsnIDs.size())
2281*0fca6ea1SDimitry Andric           << MatchTable::Comment("MergeInsnID's");
2282*0fca6ea1SDimitry Andric     for (const auto &MergeInsnID : MergeInsnIDs)
2283*0fca6ea1SDimitry Andric       Table << MatchTable::ULEB128Value(MergeInsnID);
2284*0fca6ea1SDimitry Andric     Table << MatchTable::LineBreak;
2285*0fca6ea1SDimitry Andric   }
2286*0fca6ea1SDimitry Andric 
2287*0fca6ea1SDimitry Andric   AddMIFlags();
2288*0fca6ea1SDimitry Andric }
2289*0fca6ea1SDimitry Andric 
2290*0fca6ea1SDimitry Andric //===- BuildConstantAction ------------------------------------------------===//
2291*0fca6ea1SDimitry Andric 
2292*0fca6ea1SDimitry Andric void BuildConstantAction::emitActionOpcodes(MatchTable &Table,
2293*0fca6ea1SDimitry Andric                                             RuleMatcher &Rule) const {
2294*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIR_BuildConstant")
2295*0fca6ea1SDimitry Andric         << MatchTable::Comment("TempRegID")
2296*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(TempRegID) << MatchTable::Comment("Val")
2297*0fca6ea1SDimitry Andric         << MatchTable::IntValue(8, Val) << MatchTable::LineBreak;
2298*0fca6ea1SDimitry Andric }
2299*0fca6ea1SDimitry Andric 
2300*0fca6ea1SDimitry Andric //===- EraseInstAction ----------------------------------------------------===//
2301*0fca6ea1SDimitry Andric 
2302*0fca6ea1SDimitry Andric void EraseInstAction::emitActionOpcodes(MatchTable &Table,
2303*0fca6ea1SDimitry Andric                                         RuleMatcher &Rule) const {
2304*0fca6ea1SDimitry Andric   // Avoid erasing the same inst twice.
2305*0fca6ea1SDimitry Andric   if (!Rule.tryEraseInsnID(InsnID))
2306*0fca6ea1SDimitry Andric     return;
2307*0fca6ea1SDimitry Andric 
2308*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIR_EraseFromParent")
2309*0fca6ea1SDimitry Andric         << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
2310*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
2311*0fca6ea1SDimitry Andric }
2312*0fca6ea1SDimitry Andric 
2313*0fca6ea1SDimitry Andric bool EraseInstAction::emitActionOpcodesAndDone(MatchTable &Table,
2314*0fca6ea1SDimitry Andric                                                RuleMatcher &Rule) const {
2315*0fca6ea1SDimitry Andric   if (InsnID != 0) {
2316*0fca6ea1SDimitry Andric     emitActionOpcodes(Table, Rule);
2317*0fca6ea1SDimitry Andric     return false;
2318*0fca6ea1SDimitry Andric   }
2319*0fca6ea1SDimitry Andric 
2320*0fca6ea1SDimitry Andric   if (!Rule.tryEraseInsnID(0))
2321*0fca6ea1SDimitry Andric     return false;
2322*0fca6ea1SDimitry Andric 
2323*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIR_EraseRootFromParent_Done", -1)
2324*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
2325*0fca6ea1SDimitry Andric   return true;
2326*0fca6ea1SDimitry Andric }
2327*0fca6ea1SDimitry Andric 
2328*0fca6ea1SDimitry Andric //===- ReplaceRegAction ---------------------------------------------------===//
2329*0fca6ea1SDimitry Andric 
2330*0fca6ea1SDimitry Andric void ReplaceRegAction::emitAdditionalPredicates(MatchTable &Table,
2331*0fca6ea1SDimitry Andric                                                 RuleMatcher &Rule) const {
2332*0fca6ea1SDimitry Andric   if (TempRegID != (unsigned)-1)
2333*0fca6ea1SDimitry Andric     return;
2334*0fca6ea1SDimitry Andric 
2335*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIM_CheckCanReplaceReg")
2336*0fca6ea1SDimitry Andric         << MatchTable::Comment("OldInsnID")
2337*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(OldInsnID)
2338*0fca6ea1SDimitry Andric         << MatchTable::Comment("OldOpIdx") << MatchTable::ULEB128Value(OldOpIdx)
2339*0fca6ea1SDimitry Andric         << MatchTable::Comment("NewInsnId")
2340*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(NewInsnId)
2341*0fca6ea1SDimitry Andric         << MatchTable::Comment("NewOpIdx") << MatchTable::ULEB128Value(NewOpIdx)
2342*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
2343*0fca6ea1SDimitry Andric }
2344*0fca6ea1SDimitry Andric 
2345*0fca6ea1SDimitry Andric void ReplaceRegAction::emitActionOpcodes(MatchTable &Table,
2346*0fca6ea1SDimitry Andric                                          RuleMatcher &Rule) const {
2347*0fca6ea1SDimitry Andric   if (TempRegID != (unsigned)-1) {
2348*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIR_ReplaceRegWithTempReg")
2349*0fca6ea1SDimitry Andric           << MatchTable::Comment("OldInsnID")
2350*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(OldInsnID)
2351*0fca6ea1SDimitry Andric           << MatchTable::Comment("OldOpIdx")
2352*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(OldOpIdx)
2353*0fca6ea1SDimitry Andric           << MatchTable::Comment("TempRegID")
2354*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(TempRegID) << MatchTable::LineBreak;
2355*0fca6ea1SDimitry Andric   } else {
2356*0fca6ea1SDimitry Andric     Table << MatchTable::Opcode("GIR_ReplaceReg")
2357*0fca6ea1SDimitry Andric           << MatchTable::Comment("OldInsnID")
2358*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(OldInsnID)
2359*0fca6ea1SDimitry Andric           << MatchTable::Comment("OldOpIdx")
2360*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(OldOpIdx)
2361*0fca6ea1SDimitry Andric           << MatchTable::Comment("NewInsnId")
2362*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(NewInsnId)
2363*0fca6ea1SDimitry Andric           << MatchTable::Comment("NewOpIdx")
2364*0fca6ea1SDimitry Andric           << MatchTable::ULEB128Value(NewOpIdx) << MatchTable::LineBreak;
2365*0fca6ea1SDimitry Andric   }
2366*0fca6ea1SDimitry Andric }
2367*0fca6ea1SDimitry Andric 
2368*0fca6ea1SDimitry Andric //===- ConstrainOperandToRegClassAction -----------------------------------===//
2369*0fca6ea1SDimitry Andric 
2370*0fca6ea1SDimitry Andric void ConstrainOperandToRegClassAction::emitActionOpcodes(
2371*0fca6ea1SDimitry Andric     MatchTable &Table, RuleMatcher &Rule) const {
2372*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIR_ConstrainOperandRC")
2373*0fca6ea1SDimitry Andric         << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)
2374*0fca6ea1SDimitry Andric         << MatchTable::Comment("Op") << MatchTable::ULEB128Value(OpIdx)
2375*0fca6ea1SDimitry Andric         << MatchTable::NamedValue(2, RC.getQualifiedIdName())
2376*0fca6ea1SDimitry Andric         << MatchTable::LineBreak;
2377*0fca6ea1SDimitry Andric }
2378*0fca6ea1SDimitry Andric 
2379*0fca6ea1SDimitry Andric //===- MakeTempRegisterAction ---------------------------------------------===//
2380*0fca6ea1SDimitry Andric 
2381*0fca6ea1SDimitry Andric void MakeTempRegisterAction::emitActionOpcodes(MatchTable &Table,
2382*0fca6ea1SDimitry Andric                                                RuleMatcher &Rule) const {
2383*0fca6ea1SDimitry Andric   Table << MatchTable::Opcode("GIR_MakeTempReg")
2384*0fca6ea1SDimitry Andric         << MatchTable::Comment("TempRegID")
2385*0fca6ea1SDimitry Andric         << MatchTable::ULEB128Value(TempRegID) << MatchTable::Comment("TypeID")
2386*0fca6ea1SDimitry Andric         << Ty << MatchTable::LineBreak;
2387*0fca6ea1SDimitry Andric }
2388*0fca6ea1SDimitry Andric 
2389*0fca6ea1SDimitry Andric } // namespace gi
2390*0fca6ea1SDimitry Andric } // namespace llvm
2391