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