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