14ba319b5SDimitry Andric //===--------------------- PredicateExpander.cpp --------------------------===//
24ba319b5SDimitry Andric //
34ba319b5SDimitry Andric //                     The LLVM Compiler Infrastructure
44ba319b5SDimitry Andric //
54ba319b5SDimitry Andric // This file is distributed under the University of Illinois Open Source
64ba319b5SDimitry Andric // License. See LICENSE.TXT for details.
74ba319b5SDimitry Andric //
84ba319b5SDimitry Andric //===----------------------------------------------------------------------===//
94ba319b5SDimitry Andric /// \file
104ba319b5SDimitry Andric /// Functionalities used by the Tablegen backends to expand machine predicates.
114ba319b5SDimitry Andric //
124ba319b5SDimitry Andric //===----------------------------------------------------------------------===//
134ba319b5SDimitry Andric 
144ba319b5SDimitry Andric #include "PredicateExpander.h"
15*b5893f02SDimitry Andric #include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
164ba319b5SDimitry Andric 
174ba319b5SDimitry Andric namespace llvm {
184ba319b5SDimitry Andric 
expandTrue(raw_ostream & OS)19*b5893f02SDimitry Andric void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
expandFalse(raw_ostream & OS)20*b5893f02SDimitry Andric void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
214ba319b5SDimitry Andric 
expandCheckImmOperand(raw_ostream & OS,int OpIndex,int ImmVal,StringRef FunctionMapper)22*b5893f02SDimitry Andric void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
23*b5893f02SDimitry Andric                                               int ImmVal,
24*b5893f02SDimitry Andric                                               StringRef FunctionMapper) {
25*b5893f02SDimitry Andric   if (!FunctionMapper.empty())
26*b5893f02SDimitry Andric     OS << FunctionMapper << "(";
274ba319b5SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
28*b5893f02SDimitry Andric      << ").getImm()";
29*b5893f02SDimitry Andric   if (!FunctionMapper.empty())
30*b5893f02SDimitry Andric     OS << ")";
31*b5893f02SDimitry Andric   OS << (shouldNegate() ? " != " : " == ") << ImmVal;
324ba319b5SDimitry Andric }
334ba319b5SDimitry Andric 
expandCheckImmOperand(raw_ostream & OS,int OpIndex,StringRef ImmVal,StringRef FunctionMapper)34*b5893f02SDimitry Andric void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
35*b5893f02SDimitry Andric                                               StringRef ImmVal,
36*b5893f02SDimitry Andric                                               StringRef FunctionMapper) {
37*b5893f02SDimitry Andric   if (ImmVal.empty())
38*b5893f02SDimitry Andric     expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
39*b5893f02SDimitry Andric 
40*b5893f02SDimitry Andric   if (!FunctionMapper.empty())
41*b5893f02SDimitry Andric     OS << FunctionMapper << "(";
424ba319b5SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
43*b5893f02SDimitry Andric      << ").getImm()";
44*b5893f02SDimitry Andric   if (!FunctionMapper.empty())
45*b5893f02SDimitry Andric     OS << ")";
46*b5893f02SDimitry Andric   OS << (shouldNegate() ? " != " : " == ") << ImmVal;
474ba319b5SDimitry Andric }
484ba319b5SDimitry Andric 
expandCheckImmOperandSimple(raw_ostream & OS,int OpIndex,StringRef FunctionMapper)49*b5893f02SDimitry Andric void PredicateExpander::expandCheckImmOperandSimple(raw_ostream &OS,
50*b5893f02SDimitry Andric                                                     int OpIndex,
51*b5893f02SDimitry Andric                                                     StringRef FunctionMapper) {
52*b5893f02SDimitry Andric   if (shouldNegate())
53*b5893f02SDimitry Andric     OS << "!";
54*b5893f02SDimitry Andric   if (!FunctionMapper.empty())
55*b5893f02SDimitry Andric     OS << FunctionMapper << "(";
56*b5893f02SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
57*b5893f02SDimitry Andric      << ").getImm()";
58*b5893f02SDimitry Andric   if (!FunctionMapper.empty())
59*b5893f02SDimitry Andric     OS << ")";
60*b5893f02SDimitry Andric }
61*b5893f02SDimitry Andric 
expandCheckRegOperand(raw_ostream & OS,int OpIndex,const Record * Reg,StringRef FunctionMapper)62*b5893f02SDimitry Andric void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
63*b5893f02SDimitry Andric                                               const Record *Reg,
64*b5893f02SDimitry Andric                                               StringRef FunctionMapper) {
654ba319b5SDimitry Andric   assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
664ba319b5SDimitry Andric 
67*b5893f02SDimitry Andric   if (!FunctionMapper.empty())
68*b5893f02SDimitry Andric     OS << FunctionMapper << "(";
694ba319b5SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
70*b5893f02SDimitry Andric      << ").getReg()";
71*b5893f02SDimitry Andric   if (!FunctionMapper.empty())
72*b5893f02SDimitry Andric     OS << ")";
73*b5893f02SDimitry Andric   OS << (shouldNegate() ? " != " : " == ");
744ba319b5SDimitry Andric   const StringRef Str = Reg->getValueAsString("Namespace");
754ba319b5SDimitry Andric   if (!Str.empty())
764ba319b5SDimitry Andric     OS << Str << "::";
774ba319b5SDimitry Andric   OS << Reg->getName();
784ba319b5SDimitry Andric }
794ba319b5SDimitry Andric 
80*b5893f02SDimitry Andric 
expandCheckRegOperandSimple(raw_ostream & OS,int OpIndex,StringRef FunctionMapper)81*b5893f02SDimitry Andric void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
82*b5893f02SDimitry Andric                                                     int OpIndex,
83*b5893f02SDimitry Andric                                                     StringRef FunctionMapper) {
84*b5893f02SDimitry Andric   if (shouldNegate())
85*b5893f02SDimitry Andric     OS << "!";
86*b5893f02SDimitry Andric   if (!FunctionMapper.empty())
87*b5893f02SDimitry Andric     OS << FunctionMapper << "(";
88*b5893f02SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
89*b5893f02SDimitry Andric      << ").getReg()";
90*b5893f02SDimitry Andric   if (!FunctionMapper.empty())
91*b5893f02SDimitry Andric     OS << ")";
92*b5893f02SDimitry Andric }
93*b5893f02SDimitry Andric 
expandCheckInvalidRegOperand(raw_ostream & OS,int OpIndex)94*b5893f02SDimitry Andric void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
954ba319b5SDimitry Andric                                                      int OpIndex) {
964ba319b5SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
974ba319b5SDimitry Andric      << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
984ba319b5SDimitry Andric }
994ba319b5SDimitry Andric 
expandCheckSameRegOperand(raw_ostream & OS,int First,int Second)100*b5893f02SDimitry Andric void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,
101*b5893f02SDimitry Andric                                                   int Second) {
1024ba319b5SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
1034ba319b5SDimitry Andric      << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
1044ba319b5SDimitry Andric      << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
1054ba319b5SDimitry Andric }
1064ba319b5SDimitry Andric 
expandCheckNumOperands(raw_ostream & OS,int NumOps)107*b5893f02SDimitry Andric void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
1084ba319b5SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
1094ba319b5SDimitry Andric      << (shouldNegate() ? "!= " : "== ") << NumOps;
1104ba319b5SDimitry Andric }
1114ba319b5SDimitry Andric 
expandCheckOpcode(raw_ostream & OS,const Record * Inst)112*b5893f02SDimitry Andric void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
1134ba319b5SDimitry Andric   OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
1144ba319b5SDimitry Andric      << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
1154ba319b5SDimitry Andric      << "::" << Inst->getName();
1164ba319b5SDimitry Andric }
1174ba319b5SDimitry Andric 
expandCheckOpcode(raw_ostream & OS,const RecVec & Opcodes)118*b5893f02SDimitry Andric void PredicateExpander::expandCheckOpcode(raw_ostream &OS,
1194ba319b5SDimitry Andric                                           const RecVec &Opcodes) {
1204ba319b5SDimitry Andric   assert(!Opcodes.empty() && "Expected at least one opcode to check!");
1214ba319b5SDimitry Andric   bool First = true;
1224ba319b5SDimitry Andric 
1234ba319b5SDimitry Andric   if (Opcodes.size() == 1) {
1244ba319b5SDimitry Andric     OS << "( ";
1254ba319b5SDimitry Andric     expandCheckOpcode(OS, Opcodes[0]);
1264ba319b5SDimitry Andric     OS << " )";
1274ba319b5SDimitry Andric     return;
1284ba319b5SDimitry Andric   }
1294ba319b5SDimitry Andric 
1304ba319b5SDimitry Andric   OS << '(';
1314ba319b5SDimitry Andric   increaseIndentLevel();
1324ba319b5SDimitry Andric   for (const Record *Rec : Opcodes) {
1334ba319b5SDimitry Andric     OS << '\n';
134*b5893f02SDimitry Andric     OS.indent(getIndentLevel() * 2);
1354ba319b5SDimitry Andric     if (!First)
1364ba319b5SDimitry Andric       OS << (shouldNegate() ? "&& " : "|| ");
1374ba319b5SDimitry Andric 
1384ba319b5SDimitry Andric     expandCheckOpcode(OS, Rec);
1394ba319b5SDimitry Andric     First = false;
1404ba319b5SDimitry Andric   }
1414ba319b5SDimitry Andric 
1424ba319b5SDimitry Andric   OS << '\n';
1434ba319b5SDimitry Andric   decreaseIndentLevel();
144*b5893f02SDimitry Andric   OS.indent(getIndentLevel() * 2);
1454ba319b5SDimitry Andric   OS << ')';
1464ba319b5SDimitry Andric }
1474ba319b5SDimitry Andric 
expandCheckPseudo(raw_ostream & OS,const RecVec & Opcodes)148*b5893f02SDimitry Andric void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
1494ba319b5SDimitry Andric                                           const RecVec &Opcodes) {
1504ba319b5SDimitry Andric   if (shouldExpandForMC())
1514ba319b5SDimitry Andric     expandFalse(OS);
1524ba319b5SDimitry Andric   else
1534ba319b5SDimitry Andric     expandCheckOpcode(OS, Opcodes);
1544ba319b5SDimitry Andric }
1554ba319b5SDimitry Andric 
expandPredicateSequence(raw_ostream & OS,const RecVec & Sequence,bool IsCheckAll)156*b5893f02SDimitry Andric void PredicateExpander::expandPredicateSequence(raw_ostream &OS,
1574ba319b5SDimitry Andric                                                 const RecVec &Sequence,
1584ba319b5SDimitry Andric                                                 bool IsCheckAll) {
1594ba319b5SDimitry Andric   assert(!Sequence.empty() && "Found an invalid empty predicate set!");
1604ba319b5SDimitry Andric   if (Sequence.size() == 1)
1614ba319b5SDimitry Andric     return expandPredicate(OS, Sequence[0]);
1624ba319b5SDimitry Andric 
1634ba319b5SDimitry Andric   // Okay, there is more than one predicate in the set.
1644ba319b5SDimitry Andric   bool First = true;
1654ba319b5SDimitry Andric   OS << (shouldNegate() ? "!(" : "(");
1664ba319b5SDimitry Andric   increaseIndentLevel();
1674ba319b5SDimitry Andric 
1684ba319b5SDimitry Andric   bool OldValue = shouldNegate();
1694ba319b5SDimitry Andric   setNegatePredicate(false);
1704ba319b5SDimitry Andric   for (const Record *Rec : Sequence) {
1714ba319b5SDimitry Andric     OS << '\n';
172*b5893f02SDimitry Andric     OS.indent(getIndentLevel() * 2);
1734ba319b5SDimitry Andric     if (!First)
1744ba319b5SDimitry Andric       OS << (IsCheckAll ? "&& " : "|| ");
1754ba319b5SDimitry Andric     expandPredicate(OS, Rec);
1764ba319b5SDimitry Andric     First = false;
1774ba319b5SDimitry Andric   }
1784ba319b5SDimitry Andric   OS << '\n';
1794ba319b5SDimitry Andric   decreaseIndentLevel();
180*b5893f02SDimitry Andric   OS.indent(getIndentLevel() * 2);
1814ba319b5SDimitry Andric   OS << ')';
1824ba319b5SDimitry Andric   setNegatePredicate(OldValue);
1834ba319b5SDimitry Andric }
1844ba319b5SDimitry Andric 
expandTIIFunctionCall(raw_ostream & OS,StringRef MethodName)185*b5893f02SDimitry Andric void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,
1864ba319b5SDimitry Andric                                               StringRef MethodName) {
1874ba319b5SDimitry Andric   OS << (shouldNegate() ? "!" : "");
188*b5893f02SDimitry Andric   OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");
1894ba319b5SDimitry Andric   OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
1904ba319b5SDimitry Andric }
1914ba319b5SDimitry Andric 
expandCheckIsRegOperand(raw_ostream & OS,int OpIndex)192*b5893f02SDimitry Andric void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
1934ba319b5SDimitry Andric   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
1944ba319b5SDimitry Andric      << "getOperand(" << OpIndex << ").isReg() ";
1954ba319b5SDimitry Andric }
1964ba319b5SDimitry Andric 
expandCheckIsImmOperand(raw_ostream & OS,int OpIndex)197*b5893f02SDimitry Andric void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
1984ba319b5SDimitry Andric   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
1994ba319b5SDimitry Andric      << "getOperand(" << OpIndex << ").isImm() ";
2004ba319b5SDimitry Andric }
2014ba319b5SDimitry Andric 
expandCheckFunctionPredicate(raw_ostream & OS,StringRef MCInstFn,StringRef MachineInstrFn)202*b5893f02SDimitry Andric void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
2034ba319b5SDimitry Andric                                                      StringRef MCInstFn,
2044ba319b5SDimitry Andric                                                      StringRef MachineInstrFn) {
2054ba319b5SDimitry Andric   OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
2064ba319b5SDimitry Andric      << (isByRef() ? "(MI)" : "(*MI)");
2074ba319b5SDimitry Andric }
2084ba319b5SDimitry Andric 
expandCheckNonPortable(raw_ostream & OS,StringRef Code)209*b5893f02SDimitry Andric void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
2104ba319b5SDimitry Andric                                                StringRef Code) {
2114ba319b5SDimitry Andric   if (shouldExpandForMC())
2124ba319b5SDimitry Andric     return expandFalse(OS);
2134ba319b5SDimitry Andric 
2144ba319b5SDimitry Andric   OS << '(' << Code << ')';
2154ba319b5SDimitry Andric }
2164ba319b5SDimitry Andric 
expandReturnStatement(raw_ostream & OS,const Record * Rec)217*b5893f02SDimitry Andric void PredicateExpander::expandReturnStatement(raw_ostream &OS,
2184ba319b5SDimitry Andric                                               const Record *Rec) {
219*b5893f02SDimitry Andric   std::string Buffer;
220*b5893f02SDimitry Andric   raw_string_ostream SS(Buffer);
2214ba319b5SDimitry Andric 
222*b5893f02SDimitry Andric   SS << "return ";
223*b5893f02SDimitry Andric   expandPredicate(SS, Rec);
224*b5893f02SDimitry Andric   SS << ";";
225*b5893f02SDimitry Andric   SS.flush();
226*b5893f02SDimitry Andric   OS << Buffer;
227*b5893f02SDimitry Andric }
228*b5893f02SDimitry Andric 
expandOpcodeSwitchCase(raw_ostream & OS,const Record * Rec)229*b5893f02SDimitry Andric void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
230*b5893f02SDimitry Andric                                                const Record *Rec) {
231*b5893f02SDimitry Andric   const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
232*b5893f02SDimitry Andric   for (const Record *Opcode : Opcodes) {
233*b5893f02SDimitry Andric     OS.indent(getIndentLevel() * 2);
234*b5893f02SDimitry Andric     OS << "case " << Opcode->getValueAsString("Namespace")
235*b5893f02SDimitry Andric        << "::" << Opcode->getName() << ":\n";
236*b5893f02SDimitry Andric   }
237*b5893f02SDimitry Andric 
238*b5893f02SDimitry Andric   increaseIndentLevel();
239*b5893f02SDimitry Andric   OS.indent(getIndentLevel() * 2);
240*b5893f02SDimitry Andric   expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
241*b5893f02SDimitry Andric   decreaseIndentLevel();
242*b5893f02SDimitry Andric }
243*b5893f02SDimitry Andric 
expandOpcodeSwitchStatement(raw_ostream & OS,const RecVec & Cases,const Record * Default)244*b5893f02SDimitry Andric void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,
245*b5893f02SDimitry Andric                                                     const RecVec &Cases,
246*b5893f02SDimitry Andric                                                     const Record *Default) {
247*b5893f02SDimitry Andric   std::string Buffer;
248*b5893f02SDimitry Andric   raw_string_ostream SS(Buffer);
249*b5893f02SDimitry Andric 
250*b5893f02SDimitry Andric   SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
251*b5893f02SDimitry Andric   for (const Record *Rec : Cases) {
252*b5893f02SDimitry Andric     expandOpcodeSwitchCase(SS, Rec);
253*b5893f02SDimitry Andric     SS << '\n';
254*b5893f02SDimitry Andric   }
255*b5893f02SDimitry Andric 
256*b5893f02SDimitry Andric   // Expand the default case.
257*b5893f02SDimitry Andric   SS.indent(getIndentLevel() * 2);
258*b5893f02SDimitry Andric   SS << "default:\n";
259*b5893f02SDimitry Andric 
260*b5893f02SDimitry Andric   increaseIndentLevel();
261*b5893f02SDimitry Andric   SS.indent(getIndentLevel() * 2);
262*b5893f02SDimitry Andric   expandStatement(SS, Default);
263*b5893f02SDimitry Andric   decreaseIndentLevel();
264*b5893f02SDimitry Andric   SS << '\n';
265*b5893f02SDimitry Andric 
266*b5893f02SDimitry Andric   SS.indent(getIndentLevel() * 2);
267*b5893f02SDimitry Andric   SS << "} // end of switch-stmt";
268*b5893f02SDimitry Andric   SS.flush();
269*b5893f02SDimitry Andric   OS << Buffer;
270*b5893f02SDimitry Andric }
271*b5893f02SDimitry Andric 
expandStatement(raw_ostream & OS,const Record * Rec)272*b5893f02SDimitry Andric void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
273*b5893f02SDimitry Andric   // Assume that padding has been added by the caller.
274*b5893f02SDimitry Andric   if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
275*b5893f02SDimitry Andric     expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
276*b5893f02SDimitry Andric                                 Rec->getValueAsDef("DefaultCase"));
277*b5893f02SDimitry Andric     return;
278*b5893f02SDimitry Andric   }
279*b5893f02SDimitry Andric 
280*b5893f02SDimitry Andric   if (Rec->isSubClassOf("MCReturnStatement")) {
281*b5893f02SDimitry Andric     expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
282*b5893f02SDimitry Andric     return;
283*b5893f02SDimitry Andric   }
284*b5893f02SDimitry Andric 
285*b5893f02SDimitry Andric   llvm_unreachable("No known rules to expand this MCStatement");
286*b5893f02SDimitry Andric }
287*b5893f02SDimitry Andric 
expandPredicate(raw_ostream & OS,const Record * Rec)288*b5893f02SDimitry Andric void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
289*b5893f02SDimitry Andric   // Assume that padding has been added by the caller.
2904ba319b5SDimitry Andric   if (Rec->isSubClassOf("MCTrue")) {
2914ba319b5SDimitry Andric     if (shouldNegate())
2924ba319b5SDimitry Andric       return expandFalse(OS);
2934ba319b5SDimitry Andric     return expandTrue(OS);
2944ba319b5SDimitry Andric   }
2954ba319b5SDimitry Andric 
2964ba319b5SDimitry Andric   if (Rec->isSubClassOf("MCFalse")) {
2974ba319b5SDimitry Andric     if (shouldNegate())
2984ba319b5SDimitry Andric       return expandTrue(OS);
2994ba319b5SDimitry Andric     return expandFalse(OS);
3004ba319b5SDimitry Andric   }
3014ba319b5SDimitry Andric 
3024ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckNot")) {
3034ba319b5SDimitry Andric     flipNegatePredicate();
3044ba319b5SDimitry Andric     expandPredicate(OS, Rec->getValueAsDef("Pred"));
3054ba319b5SDimitry Andric     flipNegatePredicate();
3064ba319b5SDimitry Andric     return;
3074ba319b5SDimitry Andric   }
3084ba319b5SDimitry Andric 
3094ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckIsRegOperand"))
3104ba319b5SDimitry Andric     return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
3114ba319b5SDimitry Andric 
3124ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckIsImmOperand"))
3134ba319b5SDimitry Andric     return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
3144ba319b5SDimitry Andric 
3154ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckRegOperand"))
3164ba319b5SDimitry Andric     return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
317*b5893f02SDimitry Andric                                  Rec->getValueAsDef("Reg"),
318*b5893f02SDimitry Andric                                  Rec->getValueAsString("FunctionMapper"));
319*b5893f02SDimitry Andric 
320*b5893f02SDimitry Andric   if (Rec->isSubClassOf("CheckRegOperandSimple"))
321*b5893f02SDimitry Andric     return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
322*b5893f02SDimitry Andric                                        Rec->getValueAsString("FunctionMapper"));
3234ba319b5SDimitry Andric 
3244ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckInvalidRegOperand"))
3254ba319b5SDimitry Andric     return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
3264ba319b5SDimitry Andric 
3274ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckImmOperand"))
3284ba319b5SDimitry Andric     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
329*b5893f02SDimitry Andric                                  Rec->getValueAsInt("ImmVal"),
330*b5893f02SDimitry Andric                                  Rec->getValueAsString("FunctionMapper"));
3314ba319b5SDimitry Andric 
3324ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckImmOperand_s"))
3334ba319b5SDimitry Andric     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
334*b5893f02SDimitry Andric                                  Rec->getValueAsString("ImmVal"),
335*b5893f02SDimitry Andric                                  Rec->getValueAsString("FunctionMapper"));
336*b5893f02SDimitry Andric 
337*b5893f02SDimitry Andric   if (Rec->isSubClassOf("CheckImmOperandSimple"))
338*b5893f02SDimitry Andric     return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
339*b5893f02SDimitry Andric                                        Rec->getValueAsString("FunctionMapper"));
3404ba319b5SDimitry Andric 
3414ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckSameRegOperand"))
3424ba319b5SDimitry Andric     return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
3434ba319b5SDimitry Andric                                      Rec->getValueAsInt("SecondIndex"));
3444ba319b5SDimitry Andric 
3454ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckNumOperands"))
3464ba319b5SDimitry Andric     return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
3474ba319b5SDimitry Andric 
3484ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckPseudo"))
3494ba319b5SDimitry Andric     return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
3504ba319b5SDimitry Andric 
3514ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckOpcode"))
3524ba319b5SDimitry Andric     return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
3534ba319b5SDimitry Andric 
3544ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckAll"))
3554ba319b5SDimitry Andric     return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
3564ba319b5SDimitry Andric                                    /* AllOf */ true);
3574ba319b5SDimitry Andric 
3584ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckAny"))
3594ba319b5SDimitry Andric     return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
3604ba319b5SDimitry Andric                                    /* AllOf */ false);
3614ba319b5SDimitry Andric 
3624ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckFunctionPredicate"))
3634ba319b5SDimitry Andric     return expandCheckFunctionPredicate(
3644ba319b5SDimitry Andric         OS, Rec->getValueAsString("MCInstFnName"),
3654ba319b5SDimitry Andric         Rec->getValueAsString("MachineInstrFnName"));
3664ba319b5SDimitry Andric 
3674ba319b5SDimitry Andric   if (Rec->isSubClassOf("CheckNonPortable"))
3684ba319b5SDimitry Andric     return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
3694ba319b5SDimitry Andric 
3704ba319b5SDimitry Andric   if (Rec->isSubClassOf("TIIPredicate"))
371*b5893f02SDimitry Andric     return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
3724ba319b5SDimitry Andric 
3734ba319b5SDimitry Andric   llvm_unreachable("No known rules to expand this MCInstPredicate");
3744ba319b5SDimitry Andric }
3754ba319b5SDimitry Andric 
expandHeader(raw_ostream & OS,const STIPredicateFunction & Fn)376*b5893f02SDimitry Andric void STIPredicateExpander::expandHeader(raw_ostream &OS,
377*b5893f02SDimitry Andric                                         const STIPredicateFunction &Fn) {
378*b5893f02SDimitry Andric   const Record *Rec = Fn.getDeclaration();
379*b5893f02SDimitry Andric   StringRef FunctionName = Rec->getValueAsString("Name");
380*b5893f02SDimitry Andric 
381*b5893f02SDimitry Andric   OS.indent(getIndentLevel() * 2);
382*b5893f02SDimitry Andric   OS << "bool ";
383*b5893f02SDimitry Andric   if (shouldExpandDefinition())
384*b5893f02SDimitry Andric     OS << getClassPrefix() << "::";
385*b5893f02SDimitry Andric   OS << FunctionName << "(";
386*b5893f02SDimitry Andric   if (shouldExpandForMC())
387*b5893f02SDimitry Andric     OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";
388*b5893f02SDimitry Andric   else
389*b5893f02SDimitry Andric     OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
390*b5893f02SDimitry Andric   if (Rec->getValueAsBit("UpdatesOpcodeMask"))
391*b5893f02SDimitry Andric     OS << ", APInt &Mask";
392*b5893f02SDimitry Andric   OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
393*b5893f02SDimitry Andric   if (shouldExpandDefinition()) {
394*b5893f02SDimitry Andric     OS << "{\n";
395*b5893f02SDimitry Andric     return;
396*b5893f02SDimitry Andric   }
397*b5893f02SDimitry Andric 
398*b5893f02SDimitry Andric   if (Rec->getValueAsBit("OverridesBaseClassMember"))
399*b5893f02SDimitry Andric     OS << "override";
400*b5893f02SDimitry Andric   OS << ";\n";
401*b5893f02SDimitry Andric }
402*b5893f02SDimitry Andric 
expandPrologue(raw_ostream & OS,const STIPredicateFunction & Fn)403*b5893f02SDimitry Andric void STIPredicateExpander::expandPrologue(raw_ostream &OS,
404*b5893f02SDimitry Andric                                           const STIPredicateFunction &Fn) {
405*b5893f02SDimitry Andric   RecVec Delegates = Fn.getDeclaration()->getValueAsListOfDefs("Delegates");
406*b5893f02SDimitry Andric   bool UpdatesOpcodeMask =
407*b5893f02SDimitry Andric       Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
408*b5893f02SDimitry Andric 
409*b5893f02SDimitry Andric   increaseIndentLevel();
410*b5893f02SDimitry Andric   unsigned IndentLevel = getIndentLevel();
411*b5893f02SDimitry Andric   for (const Record *Delegate : Delegates) {
412*b5893f02SDimitry Andric     OS.indent(IndentLevel * 2);
413*b5893f02SDimitry Andric     OS << "if (" << Delegate->getValueAsString("Name") << "(MI";
414*b5893f02SDimitry Andric     if (UpdatesOpcodeMask)
415*b5893f02SDimitry Andric       OS << ", Mask";
416*b5893f02SDimitry Andric     if (shouldExpandForMC())
417*b5893f02SDimitry Andric       OS << ", ProcessorID";
418*b5893f02SDimitry Andric     OS << "))\n";
419*b5893f02SDimitry Andric     OS.indent((1 + IndentLevel) * 2);
420*b5893f02SDimitry Andric     OS << "return true;\n\n";
421*b5893f02SDimitry Andric   }
422*b5893f02SDimitry Andric 
423*b5893f02SDimitry Andric   if (shouldExpandForMC())
424*b5893f02SDimitry Andric     return;
425*b5893f02SDimitry Andric 
426*b5893f02SDimitry Andric   OS.indent(IndentLevel * 2);
427*b5893f02SDimitry Andric   OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
428*b5893f02SDimitry Andric }
429*b5893f02SDimitry Andric 
expandOpcodeGroup(raw_ostream & OS,const OpcodeGroup & Group,bool ShouldUpdateOpcodeMask)430*b5893f02SDimitry Andric void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS, const OpcodeGroup &Group,
431*b5893f02SDimitry Andric                                              bool ShouldUpdateOpcodeMask) {
432*b5893f02SDimitry Andric   const OpcodeInfo &OI = Group.getOpcodeInfo();
433*b5893f02SDimitry Andric   for (const PredicateInfo &PI : OI.getPredicates()) {
434*b5893f02SDimitry Andric     const APInt &ProcModelMask = PI.ProcModelMask;
435*b5893f02SDimitry Andric     bool FirstProcID = true;
436*b5893f02SDimitry Andric     for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {
437*b5893f02SDimitry Andric       if (!ProcModelMask[I])
438*b5893f02SDimitry Andric         continue;
439*b5893f02SDimitry Andric 
440*b5893f02SDimitry Andric       if (FirstProcID) {
441*b5893f02SDimitry Andric         OS.indent(getIndentLevel() * 2);
442*b5893f02SDimitry Andric         OS << "if (ProcessorID == " << I;
443*b5893f02SDimitry Andric       } else {
444*b5893f02SDimitry Andric         OS << " || ProcessorID == " << I;
445*b5893f02SDimitry Andric       }
446*b5893f02SDimitry Andric       FirstProcID = false;
447*b5893f02SDimitry Andric     }
448*b5893f02SDimitry Andric 
449*b5893f02SDimitry Andric     OS << ") {\n";
450*b5893f02SDimitry Andric 
451*b5893f02SDimitry Andric     increaseIndentLevel();
452*b5893f02SDimitry Andric     OS.indent(getIndentLevel() * 2);
453*b5893f02SDimitry Andric     if (ShouldUpdateOpcodeMask) {
454*b5893f02SDimitry Andric       if (PI.OperandMask.isNullValue())
455*b5893f02SDimitry Andric         OS << "Mask.clearAllBits();\n";
456*b5893f02SDimitry Andric       else
457*b5893f02SDimitry Andric         OS << "Mask = " << PI.OperandMask << ";\n";
458*b5893f02SDimitry Andric       OS.indent(getIndentLevel() * 2);
459*b5893f02SDimitry Andric     }
460*b5893f02SDimitry Andric     OS << "return ";
461*b5893f02SDimitry Andric     expandPredicate(OS, PI.Predicate);
462*b5893f02SDimitry Andric     OS << ";\n";
463*b5893f02SDimitry Andric     decreaseIndentLevel();
464*b5893f02SDimitry Andric     OS.indent(getIndentLevel() * 2);
465*b5893f02SDimitry Andric     OS << "}\n";
466*b5893f02SDimitry Andric   }
467*b5893f02SDimitry Andric }
468*b5893f02SDimitry Andric 
expandBody(raw_ostream & OS,const STIPredicateFunction & Fn)469*b5893f02SDimitry Andric void STIPredicateExpander::expandBody(raw_ostream &OS,
470*b5893f02SDimitry Andric                                       const STIPredicateFunction &Fn) {
471*b5893f02SDimitry Andric   bool UpdatesOpcodeMask =
472*b5893f02SDimitry Andric       Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
473*b5893f02SDimitry Andric 
474*b5893f02SDimitry Andric   unsigned IndentLevel = getIndentLevel();
475*b5893f02SDimitry Andric   OS.indent(IndentLevel * 2);
476*b5893f02SDimitry Andric   OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
477*b5893f02SDimitry Andric   OS.indent(IndentLevel * 2);
478*b5893f02SDimitry Andric   OS << "default:\n";
479*b5893f02SDimitry Andric   OS.indent(IndentLevel * 2);
480*b5893f02SDimitry Andric   OS << "  break;";
481*b5893f02SDimitry Andric 
482*b5893f02SDimitry Andric   for (const OpcodeGroup &Group : Fn.getGroups()) {
483*b5893f02SDimitry Andric     for (const Record *Opcode : Group.getOpcodes()) {
484*b5893f02SDimitry Andric       OS << '\n';
485*b5893f02SDimitry Andric       OS.indent(IndentLevel * 2);
486*b5893f02SDimitry Andric       OS << "case " << getTargetName() << "::" << Opcode->getName() << ":";
487*b5893f02SDimitry Andric     }
488*b5893f02SDimitry Andric 
489*b5893f02SDimitry Andric     OS << '\n';
490*b5893f02SDimitry Andric     increaseIndentLevel();
491*b5893f02SDimitry Andric     expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);
492*b5893f02SDimitry Andric 
493*b5893f02SDimitry Andric     OS.indent(getIndentLevel() * 2);
494*b5893f02SDimitry Andric     OS << "break;\n";
495*b5893f02SDimitry Andric     decreaseIndentLevel();
496*b5893f02SDimitry Andric   }
497*b5893f02SDimitry Andric 
498*b5893f02SDimitry Andric   OS.indent(IndentLevel * 2);
499*b5893f02SDimitry Andric   OS << "}\n";
500*b5893f02SDimitry Andric }
501*b5893f02SDimitry Andric 
expandEpilogue(raw_ostream & OS,const STIPredicateFunction & Fn)502*b5893f02SDimitry Andric void STIPredicateExpander::expandEpilogue(raw_ostream &OS,
503*b5893f02SDimitry Andric                                           const STIPredicateFunction &Fn) {
504*b5893f02SDimitry Andric   OS << '\n';
505*b5893f02SDimitry Andric   OS.indent(getIndentLevel() * 2);
506*b5893f02SDimitry Andric   OS << "return ";
507*b5893f02SDimitry Andric   expandPredicate(OS, Fn.getDefaultReturnPredicate());
508*b5893f02SDimitry Andric   OS << ";\n";
509*b5893f02SDimitry Andric 
510*b5893f02SDimitry Andric   decreaseIndentLevel();
511*b5893f02SDimitry Andric   OS.indent(getIndentLevel() * 2);
512*b5893f02SDimitry Andric   StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");
513*b5893f02SDimitry Andric   OS << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
514*b5893f02SDimitry Andric }
515*b5893f02SDimitry Andric 
expandSTIPredicate(raw_ostream & OS,const STIPredicateFunction & Fn)516*b5893f02SDimitry Andric void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
517*b5893f02SDimitry Andric                                               const STIPredicateFunction &Fn) {
518*b5893f02SDimitry Andric   const Record *Rec = Fn.getDeclaration();
519*b5893f02SDimitry Andric   if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))
520*b5893f02SDimitry Andric     return;
521*b5893f02SDimitry Andric 
522*b5893f02SDimitry Andric   expandHeader(OS, Fn);
523*b5893f02SDimitry Andric   if (shouldExpandDefinition()) {
524*b5893f02SDimitry Andric     expandPrologue(OS, Fn);
525*b5893f02SDimitry Andric     expandBody(OS, Fn);
526*b5893f02SDimitry Andric     expandEpilogue(OS, Fn);
527*b5893f02SDimitry Andric   }
528*b5893f02SDimitry Andric }
529*b5893f02SDimitry Andric 
5304ba319b5SDimitry Andric } // namespace llvm
531