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