xref: /llvm-project/llvm/utils/TableGen/Common/PredicateExpander.cpp (revision a140931be5080543372ed833aea4e8f9c96bc4b5)
1fa3d789dSPierre van Houtryve //===--------------------- PredicateExpander.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 /// \file
9fa3d789dSPierre van Houtryve /// Functionalities used by the Tablegen backends to expand machine predicates.
10fa3d789dSPierre van Houtryve //
11fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===//
12fa3d789dSPierre van Houtryve 
13fa3d789dSPierre van Houtryve #include "PredicateExpander.h"
14fa3d789dSPierre van Houtryve #include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
15fa3d789dSPierre van Houtryve #include "llvm/TableGen/Record.h"
16fa3d789dSPierre van Houtryve 
17fa3d789dSPierre van Houtryve namespace llvm {
18fa3d789dSPierre van Houtryve 
19fa3d789dSPierre van Houtryve void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
20fa3d789dSPierre van Houtryve void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
21fa3d789dSPierre van Houtryve 
22fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
23fa3d789dSPierre van Houtryve                                               int ImmVal,
24fa3d789dSPierre van Houtryve                                               StringRef FunctionMapper) {
25fa3d789dSPierre van Houtryve   if (!FunctionMapper.empty())
26fa3d789dSPierre van Houtryve     OS << FunctionMapper << "(";
27fa3d789dSPierre van Houtryve   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
28fa3d789dSPierre van Houtryve      << ").getImm()";
29fa3d789dSPierre van Houtryve   if (!FunctionMapper.empty())
30fa3d789dSPierre van Houtryve     OS << ")";
31fa3d789dSPierre van Houtryve   OS << (shouldNegate() ? " != " : " == ") << ImmVal;
32fa3d789dSPierre van Houtryve }
33fa3d789dSPierre van Houtryve 
34fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
35fa3d789dSPierre van Houtryve                                               StringRef ImmVal,
36fa3d789dSPierre van Houtryve                                               StringRef FunctionMapper) {
37fa3d789dSPierre van Houtryve   if (ImmVal.empty())
38fa3d789dSPierre van Houtryve     expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
39fa3d789dSPierre van Houtryve 
40fa3d789dSPierre van Houtryve   if (!FunctionMapper.empty())
41fa3d789dSPierre van Houtryve     OS << FunctionMapper << "(";
42fa3d789dSPierre van Houtryve   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
43fa3d789dSPierre van Houtryve      << ").getImm()";
44fa3d789dSPierre van Houtryve   if (!FunctionMapper.empty())
45fa3d789dSPierre van Houtryve     OS << ")";
46fa3d789dSPierre van Houtryve   OS << (shouldNegate() ? " != " : " == ") << ImmVal;
47fa3d789dSPierre van Houtryve }
48fa3d789dSPierre van Houtryve 
49fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckImmOperandSimple(raw_ostream &OS,
50fa3d789dSPierre van Houtryve                                                     int OpIndex,
51fa3d789dSPierre van Houtryve                                                     StringRef FunctionMapper) {
52fa3d789dSPierre van Houtryve   if (shouldNegate())
53fa3d789dSPierre van Houtryve     OS << "!";
54fa3d789dSPierre van Houtryve   if (!FunctionMapper.empty())
55fa3d789dSPierre van Houtryve     OS << FunctionMapper << "(";
56fa3d789dSPierre van Houtryve   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
57fa3d789dSPierre van Houtryve      << ").getImm()";
58fa3d789dSPierre van Houtryve   if (!FunctionMapper.empty())
59fa3d789dSPierre van Houtryve     OS << ")";
60fa3d789dSPierre van Houtryve }
61fa3d789dSPierre van Houtryve 
62fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckImmOperandLT(raw_ostream &OS, int OpIndex,
63fa3d789dSPierre van Houtryve                                                 int ImmVal,
64fa3d789dSPierre van Houtryve                                                 StringRef FunctionMapper) {
65fa3d789dSPierre van Houtryve   if (!FunctionMapper.empty())
66fa3d789dSPierre van Houtryve     OS << FunctionMapper << "(";
67fa3d789dSPierre van Houtryve   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
68fa3d789dSPierre van Houtryve      << ").getImm()";
69fa3d789dSPierre van Houtryve   if (!FunctionMapper.empty())
70fa3d789dSPierre van Houtryve     OS << ")";
71fa3d789dSPierre van Houtryve   OS << (shouldNegate() ? " >= " : " < ") << ImmVal;
72fa3d789dSPierre van Houtryve }
73fa3d789dSPierre van Houtryve 
74fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckImmOperandGT(raw_ostream &OS, int OpIndex,
75fa3d789dSPierre van Houtryve                                                 int ImmVal,
76fa3d789dSPierre van Houtryve                                                 StringRef FunctionMapper) {
77fa3d789dSPierre van Houtryve   if (!FunctionMapper.empty())
78fa3d789dSPierre van Houtryve     OS << FunctionMapper << "(";
79fa3d789dSPierre van Houtryve   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
80fa3d789dSPierre van Houtryve      << ").getImm()";
81fa3d789dSPierre van Houtryve   if (!FunctionMapper.empty())
82fa3d789dSPierre van Houtryve     OS << ")";
83fa3d789dSPierre van Houtryve   OS << (shouldNegate() ? " <= " : " > ") << ImmVal;
84fa3d789dSPierre van Houtryve }
85fa3d789dSPierre van Houtryve 
86fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
87fa3d789dSPierre van Houtryve                                               const Record *Reg,
88fa3d789dSPierre van Houtryve                                               StringRef FunctionMapper) {
89fa3d789dSPierre van Houtryve   assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
90fa3d789dSPierre van Houtryve 
91fa3d789dSPierre van Houtryve   if (!FunctionMapper.empty())
92fa3d789dSPierre van Houtryve     OS << FunctionMapper << "(";
93fa3d789dSPierre van Houtryve   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
94fa3d789dSPierre van Houtryve      << ").getReg()";
95fa3d789dSPierre van Houtryve   if (!FunctionMapper.empty())
96fa3d789dSPierre van Houtryve     OS << ")";
97fa3d789dSPierre van Houtryve   OS << (shouldNegate() ? " != " : " == ");
98fa3d789dSPierre van Houtryve   const StringRef Str = Reg->getValueAsString("Namespace");
99fa3d789dSPierre van Houtryve   if (!Str.empty())
100fa3d789dSPierre van Houtryve     OS << Str << "::";
101fa3d789dSPierre van Houtryve   OS << Reg->getName();
102fa3d789dSPierre van Houtryve }
103fa3d789dSPierre van Houtryve 
104fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
105fa3d789dSPierre van Houtryve                                                     int OpIndex,
106fa3d789dSPierre van Houtryve                                                     StringRef FunctionMapper) {
107fa3d789dSPierre van Houtryve   if (shouldNegate())
108fa3d789dSPierre van Houtryve     OS << "!";
109fa3d789dSPierre van Houtryve   if (!FunctionMapper.empty())
110fa3d789dSPierre van Houtryve     OS << FunctionMapper << "(";
111fa3d789dSPierre van Houtryve   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
112fa3d789dSPierre van Houtryve      << ").getReg()";
113fa3d789dSPierre van Houtryve   if (!FunctionMapper.empty())
114fa3d789dSPierre van Houtryve     OS << ")";
115fa3d789dSPierre van Houtryve }
116fa3d789dSPierre van Houtryve 
117fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
118fa3d789dSPierre van Houtryve                                                      int OpIndex) {
119eb8d865cSCraig Topper   if (!shouldNegate())
120eb8d865cSCraig Topper     OS << "!";
121fa3d789dSPierre van Houtryve   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
122eb8d865cSCraig Topper      << ").getReg().isValid()";
123fa3d789dSPierre van Houtryve }
124fa3d789dSPierre van Houtryve 
125fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,
126fa3d789dSPierre van Houtryve                                                   int Second) {
127fa3d789dSPierre van Houtryve   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
128fa3d789dSPierre van Houtryve      << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
129fa3d789dSPierre van Houtryve      << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
130fa3d789dSPierre van Houtryve }
131fa3d789dSPierre van Houtryve 
132fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
133fa3d789dSPierre van Houtryve   OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
134fa3d789dSPierre van Houtryve      << (shouldNegate() ? "!= " : "== ") << NumOps;
135fa3d789dSPierre van Houtryve }
136fa3d789dSPierre van Houtryve 
137fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
138fa3d789dSPierre van Houtryve   OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
139fa3d789dSPierre van Houtryve      << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
140fa3d789dSPierre van Houtryve      << "::" << Inst->getName();
141fa3d789dSPierre van Houtryve }
142fa3d789dSPierre van Houtryve 
143fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckOpcode(raw_ostream &OS,
1442b01452cSRahul Joshi                                           ArrayRef<const Record *> Opcodes) {
145fa3d789dSPierre van Houtryve   assert(!Opcodes.empty() && "Expected at least one opcode to check!");
146fa3d789dSPierre van Houtryve   bool First = true;
147fa3d789dSPierre van Houtryve 
148fa3d789dSPierre van Houtryve   if (Opcodes.size() == 1) {
149fa3d789dSPierre van Houtryve     OS << "( ";
150fa3d789dSPierre van Houtryve     expandCheckOpcode(OS, Opcodes[0]);
151fa3d789dSPierre van Houtryve     OS << " )";
152fa3d789dSPierre van Houtryve     return;
153fa3d789dSPierre van Houtryve   }
154fa3d789dSPierre van Houtryve 
155fa3d789dSPierre van Houtryve   OS << '(';
156c92137e4SRahul Joshi   ++Indent;
157fa3d789dSPierre van Houtryve   for (const Record *Rec : Opcodes) {
158c92137e4SRahul Joshi     OS << '\n' << Indent;
159fa3d789dSPierre van Houtryve     if (!First)
160fa3d789dSPierre van Houtryve       OS << (shouldNegate() ? "&& " : "|| ");
161fa3d789dSPierre van Houtryve 
162fa3d789dSPierre van Houtryve     expandCheckOpcode(OS, Rec);
163fa3d789dSPierre van Houtryve     First = false;
164fa3d789dSPierre van Houtryve   }
165fa3d789dSPierre van Houtryve 
166c92137e4SRahul Joshi   --Indent;
167c92137e4SRahul Joshi   OS << '\n' << Indent << ')';
168fa3d789dSPierre van Houtryve }
169fa3d789dSPierre van Houtryve 
170fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
1712b01452cSRahul Joshi                                           ArrayRef<const Record *> Opcodes) {
172fa3d789dSPierre van Houtryve   if (shouldExpandForMC())
173fa3d789dSPierre van Houtryve     expandFalse(OS);
174fa3d789dSPierre van Houtryve   else
175fa3d789dSPierre van Houtryve     expandCheckOpcode(OS, Opcodes);
176fa3d789dSPierre van Houtryve }
177fa3d789dSPierre van Houtryve 
1782b01452cSRahul Joshi void PredicateExpander::expandPredicateSequence(
1792b01452cSRahul Joshi     raw_ostream &OS, ArrayRef<const Record *> Sequence, bool IsCheckAll) {
180fa3d789dSPierre van Houtryve   assert(!Sequence.empty() && "Found an invalid empty predicate set!");
181fa3d789dSPierre van Houtryve   if (Sequence.size() == 1)
182fa3d789dSPierre van Houtryve     return expandPredicate(OS, Sequence[0]);
183fa3d789dSPierre van Houtryve 
184fa3d789dSPierre van Houtryve   // Okay, there is more than one predicate in the set.
185fa3d789dSPierre van Houtryve   bool First = true;
186fa3d789dSPierre van Houtryve   OS << (shouldNegate() ? "!(" : "(");
187c92137e4SRahul Joshi   ++Indent;
188fa3d789dSPierre van Houtryve 
189fa3d789dSPierre van Houtryve   bool OldValue = shouldNegate();
190fa3d789dSPierre van Houtryve   setNegatePredicate(false);
191fa3d789dSPierre van Houtryve   for (const Record *Rec : Sequence) {
192c92137e4SRahul Joshi     OS << '\n' << Indent;
193fa3d789dSPierre van Houtryve     if (!First)
194fa3d789dSPierre van Houtryve       OS << (IsCheckAll ? "&& " : "|| ");
195fa3d789dSPierre van Houtryve     expandPredicate(OS, Rec);
196fa3d789dSPierre van Houtryve     First = false;
197fa3d789dSPierre van Houtryve   }
198c92137e4SRahul Joshi   --Indent;
199c92137e4SRahul Joshi   OS << '\n' << Indent << ')';
200fa3d789dSPierre van Houtryve   setNegatePredicate(OldValue);
201fa3d789dSPierre van Houtryve }
202fa3d789dSPierre van Houtryve 
203fa3d789dSPierre van Houtryve void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,
204fa3d789dSPierre van Houtryve                                               StringRef MethodName) {
205fa3d789dSPierre van Houtryve   OS << (shouldNegate() ? "!" : "");
206fa3d789dSPierre van Houtryve   OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");
207fa3d789dSPierre van Houtryve   OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
208fa3d789dSPierre van Houtryve }
209fa3d789dSPierre van Houtryve 
210fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
211fa3d789dSPierre van Houtryve   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
212fa3d789dSPierre van Houtryve      << "getOperand(" << OpIndex << ").isReg() ";
213fa3d789dSPierre van Houtryve }
214fa3d789dSPierre van Houtryve 
215fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckIsVRegOperand(raw_ostream &OS, int OpIndex) {
216fa3d789dSPierre van Houtryve   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
217fa3d789dSPierre van Houtryve      << "getOperand(" << OpIndex << ").getReg().isVirtual()";
218fa3d789dSPierre van Houtryve }
219fa3d789dSPierre van Houtryve 
220fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
221fa3d789dSPierre van Houtryve   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
222fa3d789dSPierre van Houtryve      << "getOperand(" << OpIndex << ").isImm() ";
223fa3d789dSPierre van Houtryve }
224fa3d789dSPierre van Houtryve 
225fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckFunctionPredicateWithTII(
226fa3d789dSPierre van Houtryve     raw_ostream &OS, StringRef MCInstFn, StringRef MachineInstrFn,
227fa3d789dSPierre van Houtryve     StringRef TIIPtr) {
228fa3d789dSPierre van Houtryve   if (!shouldExpandForMC()) {
229fa3d789dSPierre van Houtryve     OS << (TIIPtr.empty() ? "TII" : TIIPtr) << "->" << MachineInstrFn;
230fa3d789dSPierre van Houtryve     OS << (isByRef() ? "(MI)" : "(*MI)");
231fa3d789dSPierre van Houtryve     return;
232fa3d789dSPierre van Houtryve   }
233fa3d789dSPierre van Houtryve 
234fa3d789dSPierre van Houtryve   OS << MCInstFn << (isByRef() ? "(MI" : "(*MI") << ", MCII)";
235fa3d789dSPierre van Houtryve }
236fa3d789dSPierre van Houtryve 
237fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
238fa3d789dSPierre van Houtryve                                                      StringRef MCInstFn,
239fa3d789dSPierre van Houtryve                                                      StringRef MachineInstrFn) {
240fa3d789dSPierre van Houtryve   OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
241fa3d789dSPierre van Houtryve      << (isByRef() ? "(MI)" : "(*MI)");
242fa3d789dSPierre van Houtryve }
243fa3d789dSPierre van Houtryve 
244fa3d789dSPierre van Houtryve void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
245fa3d789dSPierre van Houtryve                                                StringRef Code) {
246fa3d789dSPierre van Houtryve   if (shouldExpandForMC())
247fa3d789dSPierre van Houtryve     return expandFalse(OS);
248fa3d789dSPierre van Houtryve 
249fa3d789dSPierre van Houtryve   OS << '(' << Code << ')';
250fa3d789dSPierre van Houtryve }
251fa3d789dSPierre van Houtryve 
252fa3d789dSPierre van Houtryve void PredicateExpander::expandReturnStatement(raw_ostream &OS,
253fa3d789dSPierre van Houtryve                                               const Record *Rec) {
254fa3d789dSPierre van Houtryve   std::string Buffer;
255fa3d789dSPierre van Houtryve   raw_string_ostream SS(Buffer);
256fa3d789dSPierre van Houtryve 
257fa3d789dSPierre van Houtryve   SS << "return ";
258fa3d789dSPierre van Houtryve   expandPredicate(SS, Rec);
259fa3d789dSPierre van Houtryve   SS << ";";
260fa3d789dSPierre van Houtryve   OS << Buffer;
261fa3d789dSPierre van Houtryve }
262fa3d789dSPierre van Houtryve 
263fa3d789dSPierre van Houtryve void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
264fa3d789dSPierre van Houtryve                                                const Record *Rec) {
2652b01452cSRahul Joshi   for (const Record *Opcode : Rec->getValueAsListOfDefs("Opcodes")) {
266c92137e4SRahul Joshi     OS << Indent << "case " << Opcode->getValueAsString("Namespace")
267fa3d789dSPierre van Houtryve        << "::" << Opcode->getName() << ":\n";
268fa3d789dSPierre van Houtryve   }
269fa3d789dSPierre van Houtryve 
270c92137e4SRahul Joshi   ++Indent;
271c92137e4SRahul Joshi   OS << Indent;
272fa3d789dSPierre van Houtryve   expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
273c92137e4SRahul Joshi   --Indent;
274fa3d789dSPierre van Houtryve }
275fa3d789dSPierre van Houtryve 
2762b01452cSRahul Joshi void PredicateExpander::expandOpcodeSwitchStatement(
2772b01452cSRahul Joshi     raw_ostream &OS, ArrayRef<const Record *> Cases, const Record *Default) {
278fa3d789dSPierre van Houtryve   std::string Buffer;
279fa3d789dSPierre van Houtryve   raw_string_ostream SS(Buffer);
280fa3d789dSPierre van Houtryve 
281fa3d789dSPierre van Houtryve   SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
282fa3d789dSPierre van Houtryve   for (const Record *Rec : Cases) {
283fa3d789dSPierre van Houtryve     expandOpcodeSwitchCase(SS, Rec);
284fa3d789dSPierre van Houtryve     SS << '\n';
285fa3d789dSPierre van Houtryve   }
286fa3d789dSPierre van Houtryve 
287fa3d789dSPierre van Houtryve   // Expand the default case.
288c92137e4SRahul Joshi   SS << Indent << "default:\n";
289fa3d789dSPierre van Houtryve 
290c92137e4SRahul Joshi   ++Indent;
291c92137e4SRahul Joshi   SS << Indent;
292fa3d789dSPierre van Houtryve   expandStatement(SS, Default);
293c92137e4SRahul Joshi   SS << '\n' << Indent << "} // end of switch-stmt";
294fa3d789dSPierre van Houtryve   OS << Buffer;
295fa3d789dSPierre van Houtryve }
296fa3d789dSPierre van Houtryve 
297fa3d789dSPierre van Houtryve void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
298fa3d789dSPierre van Houtryve   // Assume that padding has been added by the caller.
299fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
300*a140931bSRahul Joshi     expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
301fa3d789dSPierre van Houtryve                                 Rec->getValueAsDef("DefaultCase"));
302fa3d789dSPierre van Houtryve     return;
303fa3d789dSPierre van Houtryve   }
304fa3d789dSPierre van Houtryve 
305fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("MCReturnStatement")) {
306fa3d789dSPierre van Houtryve     expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
307fa3d789dSPierre van Houtryve     return;
308fa3d789dSPierre van Houtryve   }
309fa3d789dSPierre van Houtryve 
310fa3d789dSPierre van Houtryve   llvm_unreachable("No known rules to expand this MCStatement");
311fa3d789dSPierre van Houtryve }
312fa3d789dSPierre van Houtryve 
313fa3d789dSPierre van Houtryve void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
314fa3d789dSPierre van Houtryve   // Assume that padding has been added by the caller.
315fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("MCTrue")) {
316fa3d789dSPierre van Houtryve     if (shouldNegate())
317fa3d789dSPierre van Houtryve       return expandFalse(OS);
318fa3d789dSPierre van Houtryve     return expandTrue(OS);
319fa3d789dSPierre van Houtryve   }
320fa3d789dSPierre van Houtryve 
321fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("MCFalse")) {
322fa3d789dSPierre van Houtryve     if (shouldNegate())
323fa3d789dSPierre van Houtryve       return expandTrue(OS);
324fa3d789dSPierre van Houtryve     return expandFalse(OS);
325fa3d789dSPierre van Houtryve   }
326fa3d789dSPierre van Houtryve 
327fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckNot")) {
328fa3d789dSPierre van Houtryve     flipNegatePredicate();
329fa3d789dSPierre van Houtryve     expandPredicate(OS, Rec->getValueAsDef("Pred"));
330fa3d789dSPierre van Houtryve     flipNegatePredicate();
331fa3d789dSPierre van Houtryve     return;
332fa3d789dSPierre van Houtryve   }
333fa3d789dSPierre van Houtryve 
334fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckIsRegOperand"))
335fa3d789dSPierre van Houtryve     return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
336fa3d789dSPierre van Houtryve 
337fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckIsVRegOperand"))
338fa3d789dSPierre van Houtryve     return expandCheckIsVRegOperand(OS, Rec->getValueAsInt("OpIndex"));
339fa3d789dSPierre van Houtryve 
340fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckIsImmOperand"))
341fa3d789dSPierre van Houtryve     return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
342fa3d789dSPierre van Houtryve 
343fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckRegOperand"))
344fa3d789dSPierre van Houtryve     return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
345fa3d789dSPierre van Houtryve                                  Rec->getValueAsDef("Reg"),
346fa3d789dSPierre van Houtryve                                  Rec->getValueAsString("FunctionMapper"));
347fa3d789dSPierre van Houtryve 
348fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckRegOperandSimple"))
349fa3d789dSPierre van Houtryve     return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
350fa3d789dSPierre van Houtryve                                        Rec->getValueAsString("FunctionMapper"));
351fa3d789dSPierre van Houtryve 
352fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckInvalidRegOperand"))
353fa3d789dSPierre van Houtryve     return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
354fa3d789dSPierre van Houtryve 
355fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckImmOperand"))
356fa3d789dSPierre van Houtryve     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
357fa3d789dSPierre van Houtryve                                  Rec->getValueAsInt("ImmVal"),
358fa3d789dSPierre van Houtryve                                  Rec->getValueAsString("FunctionMapper"));
359fa3d789dSPierre van Houtryve 
360fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckImmOperand_s"))
361fa3d789dSPierre van Houtryve     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
362fa3d789dSPierre van Houtryve                                  Rec->getValueAsString("ImmVal"),
363fa3d789dSPierre van Houtryve                                  Rec->getValueAsString("FunctionMapper"));
364fa3d789dSPierre van Houtryve 
365fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckImmOperandLT"))
366fa3d789dSPierre van Houtryve     return expandCheckImmOperandLT(OS, Rec->getValueAsInt("OpIndex"),
367fa3d789dSPierre van Houtryve                                    Rec->getValueAsInt("ImmVal"),
368fa3d789dSPierre van Houtryve                                    Rec->getValueAsString("FunctionMapper"));
369fa3d789dSPierre van Houtryve 
370fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckImmOperandGT"))
371fa3d789dSPierre van Houtryve     return expandCheckImmOperandGT(OS, Rec->getValueAsInt("OpIndex"),
372fa3d789dSPierre van Houtryve                                    Rec->getValueAsInt("ImmVal"),
373fa3d789dSPierre van Houtryve                                    Rec->getValueAsString("FunctionMapper"));
374fa3d789dSPierre van Houtryve 
375fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckImmOperandSimple"))
376fa3d789dSPierre van Houtryve     return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
377fa3d789dSPierre van Houtryve                                        Rec->getValueAsString("FunctionMapper"));
378fa3d789dSPierre van Houtryve 
379fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckSameRegOperand"))
380fa3d789dSPierre van Houtryve     return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
381fa3d789dSPierre van Houtryve                                      Rec->getValueAsInt("SecondIndex"));
382fa3d789dSPierre van Houtryve 
383fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckNumOperands"))
384fa3d789dSPierre van Houtryve     return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
385fa3d789dSPierre van Houtryve 
386fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckPseudo"))
387fa3d789dSPierre van Houtryve     return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
388fa3d789dSPierre van Houtryve 
389fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckOpcode"))
390fa3d789dSPierre van Houtryve     return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
391fa3d789dSPierre van Houtryve 
392fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckAll"))
393fa3d789dSPierre van Houtryve     return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
394fa3d789dSPierre van Houtryve                                    /* AllOf */ true);
395fa3d789dSPierre van Houtryve 
396fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckAny"))
397fa3d789dSPierre van Houtryve     return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
398fa3d789dSPierre van Houtryve                                    /* AllOf */ false);
399fa3d789dSPierre van Houtryve 
400fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckFunctionPredicate")) {
401fa3d789dSPierre van Houtryve     return expandCheckFunctionPredicate(
402fa3d789dSPierre van Houtryve         OS, Rec->getValueAsString("MCInstFnName"),
403fa3d789dSPierre van Houtryve         Rec->getValueAsString("MachineInstrFnName"));
404fa3d789dSPierre van Houtryve   }
405fa3d789dSPierre van Houtryve 
406fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckFunctionPredicateWithTII")) {
407fa3d789dSPierre van Houtryve     return expandCheckFunctionPredicateWithTII(
408fa3d789dSPierre van Houtryve         OS, Rec->getValueAsString("MCInstFnName"),
409fa3d789dSPierre van Houtryve         Rec->getValueAsString("MachineInstrFnName"),
410fa3d789dSPierre van Houtryve         Rec->getValueAsString("TIIPtrName"));
411fa3d789dSPierre van Houtryve   }
412fa3d789dSPierre van Houtryve 
413fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("CheckNonPortable"))
414fa3d789dSPierre van Houtryve     return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
415fa3d789dSPierre van Houtryve 
416fa3d789dSPierre van Houtryve   if (Rec->isSubClassOf("TIIPredicate"))
417fa3d789dSPierre van Houtryve     return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
418fa3d789dSPierre van Houtryve 
419fa3d789dSPierre van Houtryve   llvm_unreachable("No known rules to expand this MCInstPredicate");
420fa3d789dSPierre van Houtryve }
421fa3d789dSPierre van Houtryve 
422fa3d789dSPierre van Houtryve void STIPredicateExpander::expandHeader(raw_ostream &OS,
423fa3d789dSPierre van Houtryve                                         const STIPredicateFunction &Fn) {
424fa3d789dSPierre van Houtryve   const Record *Rec = Fn.getDeclaration();
425fa3d789dSPierre van Houtryve   StringRef FunctionName = Rec->getValueAsString("Name");
426fa3d789dSPierre van Houtryve 
427c92137e4SRahul Joshi   OS << Indent << "bool ";
428fa3d789dSPierre van Houtryve   if (shouldExpandDefinition())
429fa3d789dSPierre van Houtryve     OS << getClassPrefix() << "::";
430fa3d789dSPierre van Houtryve   OS << FunctionName << "(";
431fa3d789dSPierre van Houtryve   if (shouldExpandForMC())
432fa3d789dSPierre van Houtryve     OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";
433fa3d789dSPierre van Houtryve   else
434fa3d789dSPierre van Houtryve     OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
435fa3d789dSPierre van Houtryve   if (Rec->getValueAsBit("UpdatesOpcodeMask"))
436fa3d789dSPierre van Houtryve     OS << ", APInt &Mask";
437fa3d789dSPierre van Houtryve   OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
438fa3d789dSPierre van Houtryve   if (shouldExpandDefinition()) {
439fa3d789dSPierre van Houtryve     OS << "{\n";
440fa3d789dSPierre van Houtryve     return;
441fa3d789dSPierre van Houtryve   }
442fa3d789dSPierre van Houtryve 
443fa3d789dSPierre van Houtryve   if (Rec->getValueAsBit("OverridesBaseClassMember"))
444fa3d789dSPierre van Houtryve     OS << "override";
445fa3d789dSPierre van Houtryve   OS << ";\n";
446fa3d789dSPierre van Houtryve }
447fa3d789dSPierre van Houtryve 
448fa3d789dSPierre van Houtryve void STIPredicateExpander::expandPrologue(raw_ostream &OS,
449fa3d789dSPierre van Houtryve                                           const STIPredicateFunction &Fn) {
450fa3d789dSPierre van Houtryve   bool UpdatesOpcodeMask =
451fa3d789dSPierre van Houtryve       Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
452fa3d789dSPierre van Houtryve 
453c92137e4SRahul Joshi   ++Indent;
4542b01452cSRahul Joshi   for (const Record *Delegate :
4552b01452cSRahul Joshi        Fn.getDeclaration()->getValueAsListOfDefs("Delegates")) {
456c92137e4SRahul Joshi     OS << Indent << "if (" << Delegate->getValueAsString("Name") << "(MI";
457fa3d789dSPierre van Houtryve     if (UpdatesOpcodeMask)
458fa3d789dSPierre van Houtryve       OS << ", Mask";
459fa3d789dSPierre van Houtryve     if (shouldExpandForMC())
460fa3d789dSPierre van Houtryve       OS << ", ProcessorID";
461fa3d789dSPierre van Houtryve     OS << "))\n";
462c92137e4SRahul Joshi     OS << Indent + 1 << "return true;\n\n";
463fa3d789dSPierre van Houtryve   }
464fa3d789dSPierre van Houtryve 
465fa3d789dSPierre van Houtryve   if (shouldExpandForMC())
466fa3d789dSPierre van Houtryve     return;
467fa3d789dSPierre van Houtryve 
468c92137e4SRahul Joshi   OS << Indent << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
469fa3d789dSPierre van Houtryve }
470fa3d789dSPierre van Houtryve 
471fa3d789dSPierre van Houtryve void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS,
472fa3d789dSPierre van Houtryve                                              const OpcodeGroup &Group,
473fa3d789dSPierre van Houtryve                                              bool ShouldUpdateOpcodeMask) {
474fa3d789dSPierre van Houtryve   const OpcodeInfo &OI = Group.getOpcodeInfo();
475fa3d789dSPierre van Houtryve   for (const PredicateInfo &PI : OI.getPredicates()) {
476fa3d789dSPierre van Houtryve     const APInt &ProcModelMask = PI.ProcModelMask;
477fa3d789dSPierre van Houtryve     bool FirstProcID = true;
478fa3d789dSPierre van Houtryve     for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {
479fa3d789dSPierre van Houtryve       if (!ProcModelMask[I])
480fa3d789dSPierre van Houtryve         continue;
481fa3d789dSPierre van Houtryve 
482fa3d789dSPierre van Houtryve       if (FirstProcID) {
483c92137e4SRahul Joshi         OS << Indent << "if (ProcessorID == " << I;
484fa3d789dSPierre van Houtryve       } else {
485fa3d789dSPierre van Houtryve         OS << " || ProcessorID == " << I;
486fa3d789dSPierre van Houtryve       }
487fa3d789dSPierre van Houtryve       FirstProcID = false;
488fa3d789dSPierre van Houtryve     }
489fa3d789dSPierre van Houtryve 
490fa3d789dSPierre van Houtryve     OS << ") {\n";
491fa3d789dSPierre van Houtryve 
492c92137e4SRahul Joshi     ++Indent;
493c92137e4SRahul Joshi     OS << Indent;
494fa3d789dSPierre van Houtryve     if (ShouldUpdateOpcodeMask) {
495fa3d789dSPierre van Houtryve       if (PI.OperandMask.isZero())
496fa3d789dSPierre van Houtryve         OS << "Mask.clearAllBits();\n";
497fa3d789dSPierre van Houtryve       else
498fa3d789dSPierre van Houtryve         OS << "Mask = " << PI.OperandMask << ";\n";
499c92137e4SRahul Joshi       OS << Indent;
500fa3d789dSPierre van Houtryve     }
501fa3d789dSPierre van Houtryve     OS << "return ";
502fa3d789dSPierre van Houtryve     expandPredicate(OS, PI.Predicate);
503fa3d789dSPierre van Houtryve     OS << ";\n";
504c92137e4SRahul Joshi     --Indent;
505c92137e4SRahul Joshi     OS << Indent << "}\n";
506fa3d789dSPierre van Houtryve   }
507fa3d789dSPierre van Houtryve }
508fa3d789dSPierre van Houtryve 
509fa3d789dSPierre van Houtryve void STIPredicateExpander::expandBody(raw_ostream &OS,
510fa3d789dSPierre van Houtryve                                       const STIPredicateFunction &Fn) {
511fa3d789dSPierre van Houtryve   bool UpdatesOpcodeMask =
512fa3d789dSPierre van Houtryve       Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
513fa3d789dSPierre van Houtryve 
514c92137e4SRahul Joshi   OS << Indent << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
515c92137e4SRahul Joshi   OS << Indent << "default:\n";
516c92137e4SRahul Joshi   OS << Indent << "  break;";
517fa3d789dSPierre van Houtryve 
518fa3d789dSPierre van Houtryve   for (const OpcodeGroup &Group : Fn.getGroups()) {
519fa3d789dSPierre van Houtryve     for (const Record *Opcode : Group.getOpcodes()) {
520c92137e4SRahul Joshi       OS << '\n'
521c92137e4SRahul Joshi          << Indent << "case " << getTargetName() << "::" << Opcode->getName()
522c92137e4SRahul Joshi          << ":";
523fa3d789dSPierre van Houtryve     }
524fa3d789dSPierre van Houtryve 
525fa3d789dSPierre van Houtryve     OS << '\n';
526c92137e4SRahul Joshi     ++Indent;
527fa3d789dSPierre van Houtryve     expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);
528fa3d789dSPierre van Houtryve 
529c92137e4SRahul Joshi     OS << Indent << "break;\n";
530c92137e4SRahul Joshi     --Indent;
531fa3d789dSPierre van Houtryve   }
532fa3d789dSPierre van Houtryve 
533c92137e4SRahul Joshi   OS << Indent << "}\n";
534fa3d789dSPierre van Houtryve }
535fa3d789dSPierre van Houtryve 
536fa3d789dSPierre van Houtryve void STIPredicateExpander::expandEpilogue(raw_ostream &OS,
537fa3d789dSPierre van Houtryve                                           const STIPredicateFunction &Fn) {
538c92137e4SRahul Joshi   OS << '\n' << Indent;
539fa3d789dSPierre van Houtryve   OS << "return ";
540fa3d789dSPierre van Houtryve   expandPredicate(OS, Fn.getDefaultReturnPredicate());
541fa3d789dSPierre van Houtryve   OS << ";\n";
542fa3d789dSPierre van Houtryve 
543c92137e4SRahul Joshi   --Indent;
544fa3d789dSPierre van Houtryve   StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");
545c92137e4SRahul Joshi   OS << Indent << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
546fa3d789dSPierre van Houtryve }
547fa3d789dSPierre van Houtryve 
548fa3d789dSPierre van Houtryve void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
549fa3d789dSPierre van Houtryve                                               const STIPredicateFunction &Fn) {
550fa3d789dSPierre van Houtryve   const Record *Rec = Fn.getDeclaration();
551fa3d789dSPierre van Houtryve   if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))
552fa3d789dSPierre van Houtryve     return;
553fa3d789dSPierre van Houtryve 
554fa3d789dSPierre van Houtryve   expandHeader(OS, Fn);
555fa3d789dSPierre van Houtryve   if (shouldExpandDefinition()) {
556fa3d789dSPierre van Houtryve     expandPrologue(OS, Fn);
557fa3d789dSPierre van Houtryve     expandBody(OS, Fn);
558fa3d789dSPierre van Houtryve     expandEpilogue(OS, Fn);
559fa3d789dSPierre van Houtryve   }
560fa3d789dSPierre van Houtryve }
561fa3d789dSPierre van Houtryve 
562fa3d789dSPierre van Houtryve } // namespace llvm
563