195140023SAndrea Di Biagio //===--------------------- PredicateExpander.cpp --------------------------===//
295140023SAndrea Di Biagio //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
695140023SAndrea Di Biagio //
795140023SAndrea Di Biagio //===----------------------------------------------------------------------===//
895140023SAndrea Di Biagio /// \file
995140023SAndrea Di Biagio /// Functionalities used by the Tablegen backends to expand machine predicates.
1095140023SAndrea Di Biagio //
1195140023SAndrea Di Biagio //===----------------------------------------------------------------------===//
1295140023SAndrea Di Biagio 
1395140023SAndrea Di Biagio #include "PredicateExpander.h"
148b6c314bSAndrea Di Biagio #include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
1595140023SAndrea Di Biagio 
1695140023SAndrea Di Biagio namespace llvm {
1795140023SAndrea Di Biagio 
expandTrue(raw_ostream & OS)182c6cbc8bSAndrea Di Biagio void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
expandFalse(raw_ostream & OS)192c6cbc8bSAndrea Di Biagio void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
2095140023SAndrea Di Biagio 
expandCheckImmOperand(raw_ostream & OS,int OpIndex,int ImmVal,StringRef FunctionMapper)212c6cbc8bSAndrea Di Biagio void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
223d2b7176SAndrea Di Biagio                                               int ImmVal,
233d2b7176SAndrea Di Biagio                                               StringRef FunctionMapper) {
243d2b7176SAndrea Di Biagio   if (!FunctionMapper.empty())
253d2b7176SAndrea Di Biagio     OS << FunctionMapper << "(";
26ad0293caSAndrea Di Biagio   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
273d2b7176SAndrea Di Biagio      << ").getImm()";
2858e94f91SEvandro Menezes   if (!FunctionMapper.empty())
2958e94f91SEvandro Menezes     OS << ")";
303d2b7176SAndrea Di Biagio   OS << (shouldNegate() ? " != " : " == ") << ImmVal;
3195140023SAndrea Di Biagio }
3295140023SAndrea Di Biagio 
expandCheckImmOperand(raw_ostream & OS,int OpIndex,StringRef ImmVal,StringRef FunctionMapper)332c6cbc8bSAndrea Di Biagio void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
343d2b7176SAndrea Di Biagio                                               StringRef ImmVal,
353d2b7176SAndrea Di Biagio                                               StringRef FunctionMapper) {
3658e94f91SEvandro Menezes   if (ImmVal.empty())
3758e94f91SEvandro Menezes     expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
3858e94f91SEvandro Menezes 
393d2b7176SAndrea Di Biagio   if (!FunctionMapper.empty())
403d2b7176SAndrea Di Biagio     OS << FunctionMapper << "(";
41ad0293caSAndrea Di Biagio   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
423d2b7176SAndrea Di Biagio      << ").getImm()";
4358e94f91SEvandro Menezes   if (!FunctionMapper.empty())
4458e94f91SEvandro Menezes     OS << ")";
453d2b7176SAndrea Di Biagio   OS << (shouldNegate() ? " != " : " == ") << ImmVal;
4695140023SAndrea Di Biagio }
4795140023SAndrea Di Biagio 
expandCheckImmOperandSimple(raw_ostream & OS,int OpIndex,StringRef FunctionMapper)4858e94f91SEvandro Menezes void PredicateExpander::expandCheckImmOperandSimple(raw_ostream &OS,
4958e94f91SEvandro Menezes                                                     int OpIndex,
5058e94f91SEvandro Menezes                                                     StringRef FunctionMapper) {
5158e94f91SEvandro Menezes   if (shouldNegate())
5258e94f91SEvandro Menezes     OS << "!";
5358e94f91SEvandro Menezes   if (!FunctionMapper.empty())
5458e94f91SEvandro Menezes     OS << FunctionMapper << "(";
5558e94f91SEvandro Menezes   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
5658e94f91SEvandro Menezes      << ").getImm()";
5758e94f91SEvandro Menezes   if (!FunctionMapper.empty())
5858e94f91SEvandro Menezes     OS << ")";
5958e94f91SEvandro Menezes }
6058e94f91SEvandro Menezes 
expandCheckRegOperand(raw_ostream & OS,int OpIndex,const Record * Reg,StringRef FunctionMapper)612c6cbc8bSAndrea Di Biagio void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
623d2b7176SAndrea Di Biagio                                               const Record *Reg,
633d2b7176SAndrea Di Biagio                                               StringRef FunctionMapper) {
6495140023SAndrea Di Biagio   assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
6595140023SAndrea Di Biagio 
663d2b7176SAndrea Di Biagio   if (!FunctionMapper.empty())
673d2b7176SAndrea Di Biagio     OS << FunctionMapper << "(";
6895140023SAndrea Di Biagio   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
693d2b7176SAndrea Di Biagio      << ").getReg()";
7058e94f91SEvandro Menezes   if (!FunctionMapper.empty())
7158e94f91SEvandro Menezes     OS << ")";
723d2b7176SAndrea Di Biagio   OS << (shouldNegate() ? " != " : " == ");
7395140023SAndrea Di Biagio   const StringRef Str = Reg->getValueAsString("Namespace");
7495140023SAndrea Di Biagio   if (!Str.empty())
7595140023SAndrea Di Biagio     OS << Str << "::";
7695140023SAndrea Di Biagio   OS << Reg->getName();
7795140023SAndrea Di Biagio }
7895140023SAndrea Di Biagio 
7958e94f91SEvandro Menezes 
expandCheckRegOperandSimple(raw_ostream & OS,int OpIndex,StringRef FunctionMapper)8058e94f91SEvandro Menezes void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
8158e94f91SEvandro Menezes                                                     int OpIndex,
8258e94f91SEvandro Menezes                                                     StringRef FunctionMapper) {
8358e94f91SEvandro Menezes   if (shouldNegate())
8458e94f91SEvandro Menezes     OS << "!";
8558e94f91SEvandro Menezes   if (!FunctionMapper.empty())
8658e94f91SEvandro Menezes     OS << FunctionMapper << "(";
8758e94f91SEvandro Menezes   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
8858e94f91SEvandro Menezes      << ").getReg()";
8958e94f91SEvandro Menezes   if (!FunctionMapper.empty())
9058e94f91SEvandro Menezes     OS << ")";
9158e94f91SEvandro Menezes }
9258e94f91SEvandro Menezes 
expandCheckInvalidRegOperand(raw_ostream & OS,int OpIndex)932c6cbc8bSAndrea Di Biagio void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
949a2e9db7SAndrea Di Biagio                                                      int OpIndex) {
959a2e9db7SAndrea Di Biagio   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
969a2e9db7SAndrea Di Biagio      << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
979a2e9db7SAndrea Di Biagio }
989a2e9db7SAndrea Di Biagio 
expandCheckSameRegOperand(raw_ostream & OS,int First,int Second)992c6cbc8bSAndrea Di Biagio void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,
1002c6cbc8bSAndrea Di Biagio                                                   int Second) {
10195140023SAndrea Di Biagio   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
10295140023SAndrea Di Biagio      << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
10395140023SAndrea Di Biagio      << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
10495140023SAndrea Di Biagio }
10595140023SAndrea Di Biagio 
expandCheckNumOperands(raw_ostream & OS,int NumOps)1062c6cbc8bSAndrea Di Biagio void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
10795140023SAndrea Di Biagio   OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
10895140023SAndrea Di Biagio      << (shouldNegate() ? "!= " : "== ") << NumOps;
10995140023SAndrea Di Biagio }
11095140023SAndrea Di Biagio 
expandCheckOpcode(raw_ostream & OS,const Record * Inst)1112c6cbc8bSAndrea Di Biagio void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
11295140023SAndrea Di Biagio   OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
11395140023SAndrea Di Biagio      << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
11495140023SAndrea Di Biagio      << "::" << Inst->getName();
11595140023SAndrea Di Biagio }
11695140023SAndrea Di Biagio 
expandCheckOpcode(raw_ostream & OS,const RecVec & Opcodes)1172c6cbc8bSAndrea Di Biagio void PredicateExpander::expandCheckOpcode(raw_ostream &OS,
11895140023SAndrea Di Biagio                                           const RecVec &Opcodes) {
11995140023SAndrea Di Biagio   assert(!Opcodes.empty() && "Expected at least one opcode to check!");
12095140023SAndrea Di Biagio   bool First = true;
12195140023SAndrea Di Biagio 
12295140023SAndrea Di Biagio   if (Opcodes.size() == 1) {
12395140023SAndrea Di Biagio     OS << "( ";
12495140023SAndrea Di Biagio     expandCheckOpcode(OS, Opcodes[0]);
12595140023SAndrea Di Biagio     OS << " )";
12695140023SAndrea Di Biagio     return;
12795140023SAndrea Di Biagio   }
12895140023SAndrea Di Biagio 
12995140023SAndrea Di Biagio   OS << '(';
13095140023SAndrea Di Biagio   increaseIndentLevel();
13195140023SAndrea Di Biagio   for (const Record *Rec : Opcodes) {
13295140023SAndrea Di Biagio     OS << '\n';
1332c6cbc8bSAndrea Di Biagio     OS.indent(getIndentLevel() * 2);
13495140023SAndrea Di Biagio     if (!First)
13595140023SAndrea Di Biagio       OS << (shouldNegate() ? "&& " : "|| ");
13695140023SAndrea Di Biagio 
13795140023SAndrea Di Biagio     expandCheckOpcode(OS, Rec);
13895140023SAndrea Di Biagio     First = false;
13995140023SAndrea Di Biagio   }
14095140023SAndrea Di Biagio 
14195140023SAndrea Di Biagio   OS << '\n';
14295140023SAndrea Di Biagio   decreaseIndentLevel();
1432c6cbc8bSAndrea Di Biagio   OS.indent(getIndentLevel() * 2);
14495140023SAndrea Di Biagio   OS << ')';
14595140023SAndrea Di Biagio }
14695140023SAndrea Di Biagio 
expandCheckPseudo(raw_ostream & OS,const RecVec & Opcodes)1472c6cbc8bSAndrea Di Biagio void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
14895140023SAndrea Di Biagio                                           const RecVec &Opcodes) {
14995140023SAndrea Di Biagio   if (shouldExpandForMC())
15095140023SAndrea Di Biagio     expandFalse(OS);
15195140023SAndrea Di Biagio   else
15295140023SAndrea Di Biagio     expandCheckOpcode(OS, Opcodes);
15395140023SAndrea Di Biagio }
15495140023SAndrea Di Biagio 
expandPredicateSequence(raw_ostream & OS,const RecVec & Sequence,bool IsCheckAll)1552c6cbc8bSAndrea Di Biagio void PredicateExpander::expandPredicateSequence(raw_ostream &OS,
15695140023SAndrea Di Biagio                                                 const RecVec &Sequence,
15795140023SAndrea Di Biagio                                                 bool IsCheckAll) {
15895140023SAndrea Di Biagio   assert(!Sequence.empty() && "Found an invalid empty predicate set!");
15995140023SAndrea Di Biagio   if (Sequence.size() == 1)
16095140023SAndrea Di Biagio     return expandPredicate(OS, Sequence[0]);
16195140023SAndrea Di Biagio 
16295140023SAndrea Di Biagio   // Okay, there is more than one predicate in the set.
16395140023SAndrea Di Biagio   bool First = true;
16495140023SAndrea Di Biagio   OS << (shouldNegate() ? "!(" : "(");
16595140023SAndrea Di Biagio   increaseIndentLevel();
16695140023SAndrea Di Biagio 
16795140023SAndrea Di Biagio   bool OldValue = shouldNegate();
16895140023SAndrea Di Biagio   setNegatePredicate(false);
16995140023SAndrea Di Biagio   for (const Record *Rec : Sequence) {
17095140023SAndrea Di Biagio     OS << '\n';
1712c6cbc8bSAndrea Di Biagio     OS.indent(getIndentLevel() * 2);
17295140023SAndrea Di Biagio     if (!First)
17395140023SAndrea Di Biagio       OS << (IsCheckAll ? "&& " : "|| ");
17495140023SAndrea Di Biagio     expandPredicate(OS, Rec);
17595140023SAndrea Di Biagio     First = false;
17695140023SAndrea Di Biagio   }
17795140023SAndrea Di Biagio   OS << '\n';
17895140023SAndrea Di Biagio   decreaseIndentLevel();
1792c6cbc8bSAndrea Di Biagio   OS.indent(getIndentLevel() * 2);
18095140023SAndrea Di Biagio   OS << ')';
18195140023SAndrea Di Biagio   setNegatePredicate(OldValue);
18295140023SAndrea Di Biagio }
18395140023SAndrea Di Biagio 
expandTIIFunctionCall(raw_ostream & OS,StringRef MethodName)1842c6cbc8bSAndrea Di Biagio void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,
18595140023SAndrea Di Biagio                                               StringRef MethodName) {
18695140023SAndrea Di Biagio   OS << (shouldNegate() ? "!" : "");
1873d2b7176SAndrea Di Biagio   OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");
18895140023SAndrea Di Biagio   OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
18995140023SAndrea Di Biagio }
19095140023SAndrea Di Biagio 
expandCheckIsRegOperand(raw_ostream & OS,int OpIndex)1912c6cbc8bSAndrea Di Biagio void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
19295140023SAndrea Di Biagio   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
19395140023SAndrea Di Biagio      << "getOperand(" << OpIndex << ").isReg() ";
19495140023SAndrea Di Biagio }
19595140023SAndrea Di Biagio 
expandCheckIsImmOperand(raw_ostream & OS,int OpIndex)1962c6cbc8bSAndrea Di Biagio void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
19795140023SAndrea Di Biagio   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
19895140023SAndrea Di Biagio      << "getOperand(" << OpIndex << ").isImm() ";
19995140023SAndrea Di Biagio }
20095140023SAndrea Di Biagio 
expandCheckFunctionPredicateWithTII(raw_ostream & OS,StringRef MCInstFn,StringRef MachineInstrFn,StringRef TIIPtr)2018a7ca143SEvgeny Leviant void PredicateExpander::expandCheckFunctionPredicateWithTII(
2028a7ca143SEvgeny Leviant     raw_ostream &OS, StringRef MCInstFn, StringRef MachineInstrFn,
2038a7ca143SEvgeny Leviant     StringRef TIIPtr) {
2048a7ca143SEvgeny Leviant   if (!shouldExpandForMC()) {
2058a7ca143SEvgeny Leviant     OS << (TIIPtr.empty() ? "TII" : TIIPtr) << "->" << MachineInstrFn;
2068a7ca143SEvgeny Leviant     OS << (isByRef() ? "(MI)" : "(*MI)");
2078a7ca143SEvgeny Leviant     return;
2088a7ca143SEvgeny Leviant   }
2098a7ca143SEvgeny Leviant 
2108a7ca143SEvgeny Leviant   OS << MCInstFn << (isByRef() ? "(MI" : "(*MI") << ", MCII)";
2118a7ca143SEvgeny Leviant }
2128a7ca143SEvgeny Leviant 
expandCheckFunctionPredicate(raw_ostream & OS,StringRef MCInstFn,StringRef MachineInstrFn)2132c6cbc8bSAndrea Di Biagio void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
21495140023SAndrea Di Biagio                                                      StringRef MCInstFn,
21595140023SAndrea Di Biagio                                                      StringRef MachineInstrFn) {
21695140023SAndrea Di Biagio   OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
21795140023SAndrea Di Biagio      << (isByRef() ? "(MI)" : "(*MI)");
21895140023SAndrea Di Biagio }
21995140023SAndrea Di Biagio 
expandCheckNonPortable(raw_ostream & OS,StringRef Code)2202c6cbc8bSAndrea Di Biagio void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
22195140023SAndrea Di Biagio                                                StringRef Code) {
22295140023SAndrea Di Biagio   if (shouldExpandForMC())
22395140023SAndrea Di Biagio     return expandFalse(OS);
22495140023SAndrea Di Biagio 
22595140023SAndrea Di Biagio   OS << '(' << Code << ')';
22695140023SAndrea Di Biagio }
22795140023SAndrea Di Biagio 
expandReturnStatement(raw_ostream & OS,const Record * Rec)2282c6cbc8bSAndrea Di Biagio void PredicateExpander::expandReturnStatement(raw_ostream &OS,
229f3bde048SAndrea Di Biagio                                               const Record *Rec) {
2302c6cbc8bSAndrea Di Biagio   std::string Buffer;
2312c6cbc8bSAndrea Di Biagio   raw_string_ostream SS(Buffer);
2322c6cbc8bSAndrea Di Biagio 
2332c6cbc8bSAndrea Di Biagio   SS << "return ";
2342c6cbc8bSAndrea Di Biagio   expandPredicate(SS, Rec);
2352c6cbc8bSAndrea Di Biagio   SS << ";";
2362c6cbc8bSAndrea Di Biagio   OS << Buffer;
237f3bde048SAndrea Di Biagio }
238f3bde048SAndrea Di Biagio 
expandOpcodeSwitchCase(raw_ostream & OS,const Record * Rec)2392c6cbc8bSAndrea Di Biagio void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
240f3bde048SAndrea Di Biagio                                                const Record *Rec) {
241f3bde048SAndrea Di Biagio   const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
242f3bde048SAndrea Di Biagio   for (const Record *Opcode : Opcodes) {
2432c6cbc8bSAndrea Di Biagio     OS.indent(getIndentLevel() * 2);
244f3bde048SAndrea Di Biagio     OS << "case " << Opcode->getValueAsString("Namespace")
245f3bde048SAndrea Di Biagio        << "::" << Opcode->getName() << ":\n";
246f3bde048SAndrea Di Biagio   }
247f3bde048SAndrea Di Biagio 
248f3bde048SAndrea Di Biagio   increaseIndentLevel();
2492c6cbc8bSAndrea Di Biagio   OS.indent(getIndentLevel() * 2);
250f3bde048SAndrea Di Biagio   expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
251f3bde048SAndrea Di Biagio   decreaseIndentLevel();
252f3bde048SAndrea Di Biagio }
253f3bde048SAndrea Di Biagio 
expandOpcodeSwitchStatement(raw_ostream & OS,const RecVec & Cases,const Record * Default)2542c6cbc8bSAndrea Di Biagio void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,
255f3bde048SAndrea Di Biagio                                                     const RecVec &Cases,
256f3bde048SAndrea Di Biagio                                                     const Record *Default) {
2572c6cbc8bSAndrea Di Biagio   std::string Buffer;
2582c6cbc8bSAndrea Di Biagio   raw_string_ostream SS(Buffer);
259f3bde048SAndrea Di Biagio 
2602c6cbc8bSAndrea Di Biagio   SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
261f3bde048SAndrea Di Biagio   for (const Record *Rec : Cases) {
2622c6cbc8bSAndrea Di Biagio     expandOpcodeSwitchCase(SS, Rec);
2632c6cbc8bSAndrea Di Biagio     SS << '\n';
264f3bde048SAndrea Di Biagio   }
265f3bde048SAndrea Di Biagio 
266f3bde048SAndrea Di Biagio   // Expand the default case.
2672c6cbc8bSAndrea Di Biagio   SS.indent(getIndentLevel() * 2);
2682c6cbc8bSAndrea Di Biagio   SS << "default:\n";
269f3bde048SAndrea Di Biagio 
2702c6cbc8bSAndrea Di Biagio   increaseIndentLevel();
2712c6cbc8bSAndrea Di Biagio   SS.indent(getIndentLevel() * 2);
2722c6cbc8bSAndrea Di Biagio   expandStatement(SS, Default);
2732c6cbc8bSAndrea Di Biagio   decreaseIndentLevel();
2742c6cbc8bSAndrea Di Biagio   SS << '\n';
2752c6cbc8bSAndrea Di Biagio 
2762c6cbc8bSAndrea Di Biagio   SS.indent(getIndentLevel() * 2);
2772c6cbc8bSAndrea Di Biagio   SS << "} // end of switch-stmt";
2782c6cbc8bSAndrea Di Biagio   OS << Buffer;
279f3bde048SAndrea Di Biagio }
280f3bde048SAndrea Di Biagio 
expandStatement(raw_ostream & OS,const Record * Rec)2812c6cbc8bSAndrea Di Biagio void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
2822c6cbc8bSAndrea Di Biagio   // Assume that padding has been added by the caller.
283f3bde048SAndrea Di Biagio   if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
284f3bde048SAndrea Di Biagio     expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
285f3bde048SAndrea Di Biagio                                 Rec->getValueAsDef("DefaultCase"));
286f3bde048SAndrea Di Biagio     return;
287f3bde048SAndrea Di Biagio   }
288f3bde048SAndrea Di Biagio 
289f3bde048SAndrea Di Biagio   if (Rec->isSubClassOf("MCReturnStatement")) {
290f3bde048SAndrea Di Biagio     expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
291f3bde048SAndrea Di Biagio     return;
292f3bde048SAndrea Di Biagio   }
293f3bde048SAndrea Di Biagio 
294f3bde048SAndrea Di Biagio   llvm_unreachable("No known rules to expand this MCStatement");
295f3bde048SAndrea Di Biagio }
296f3bde048SAndrea Di Biagio 
expandPredicate(raw_ostream & OS,const Record * Rec)2972c6cbc8bSAndrea Di Biagio void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
2982c6cbc8bSAndrea Di Biagio   // Assume that padding has been added by the caller.
29995140023SAndrea Di Biagio   if (Rec->isSubClassOf("MCTrue")) {
30095140023SAndrea Di Biagio     if (shouldNegate())
30195140023SAndrea Di Biagio       return expandFalse(OS);
30295140023SAndrea Di Biagio     return expandTrue(OS);
30395140023SAndrea Di Biagio   }
30495140023SAndrea Di Biagio 
30595140023SAndrea Di Biagio   if (Rec->isSubClassOf("MCFalse")) {
30695140023SAndrea Di Biagio     if (shouldNegate())
30795140023SAndrea Di Biagio       return expandTrue(OS);
30895140023SAndrea Di Biagio     return expandFalse(OS);
30995140023SAndrea Di Biagio   }
31095140023SAndrea Di Biagio 
31195140023SAndrea Di Biagio   if (Rec->isSubClassOf("CheckNot")) {
31295140023SAndrea Di Biagio     flipNegatePredicate();
31395140023SAndrea Di Biagio     expandPredicate(OS, Rec->getValueAsDef("Pred"));
31495140023SAndrea Di Biagio     flipNegatePredicate();
31595140023SAndrea Di Biagio     return;
31695140023SAndrea Di Biagio   }
31795140023SAndrea Di Biagio 
31895140023SAndrea Di Biagio   if (Rec->isSubClassOf("CheckIsRegOperand"))
31995140023SAndrea Di Biagio     return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
32095140023SAndrea Di Biagio 
32195140023SAndrea Di Biagio   if (Rec->isSubClassOf("CheckIsImmOperand"))
32295140023SAndrea Di Biagio     return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
32395140023SAndrea Di Biagio 
32495140023SAndrea Di Biagio   if (Rec->isSubClassOf("CheckRegOperand"))
32595140023SAndrea Di Biagio     return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
3263d2b7176SAndrea Di Biagio                                  Rec->getValueAsDef("Reg"),
3273d2b7176SAndrea Di Biagio                                  Rec->getValueAsString("FunctionMapper"));
3283d2b7176SAndrea Di Biagio 
3293d2b7176SAndrea Di Biagio   if (Rec->isSubClassOf("CheckRegOperandSimple"))
33058e94f91SEvandro Menezes     return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
3313d2b7176SAndrea Di Biagio                                        Rec->getValueAsString("FunctionMapper"));
33295140023SAndrea Di Biagio 
3339a2e9db7SAndrea Di Biagio   if (Rec->isSubClassOf("CheckInvalidRegOperand"))
3349a2e9db7SAndrea Di Biagio     return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
3359a2e9db7SAndrea Di Biagio 
33695140023SAndrea Di Biagio   if (Rec->isSubClassOf("CheckImmOperand"))
33795140023SAndrea Di Biagio     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
3383d2b7176SAndrea Di Biagio                                  Rec->getValueAsInt("ImmVal"),
3393d2b7176SAndrea Di Biagio                                  Rec->getValueAsString("FunctionMapper"));
34095140023SAndrea Di Biagio 
34195140023SAndrea Di Biagio   if (Rec->isSubClassOf("CheckImmOperand_s"))
34295140023SAndrea Di Biagio     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
3433d2b7176SAndrea Di Biagio                                  Rec->getValueAsString("ImmVal"),
3443d2b7176SAndrea Di Biagio                                  Rec->getValueAsString("FunctionMapper"));
3453d2b7176SAndrea Di Biagio 
3463d2b7176SAndrea Di Biagio   if (Rec->isSubClassOf("CheckImmOperandSimple"))
34758e94f91SEvandro Menezes     return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
3483d2b7176SAndrea Di Biagio                                        Rec->getValueAsString("FunctionMapper"));
34995140023SAndrea Di Biagio 
35095140023SAndrea Di Biagio   if (Rec->isSubClassOf("CheckSameRegOperand"))
35195140023SAndrea Di Biagio     return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
35295140023SAndrea Di Biagio                                      Rec->getValueAsInt("SecondIndex"));
35395140023SAndrea Di Biagio 
35495140023SAndrea Di Biagio   if (Rec->isSubClassOf("CheckNumOperands"))
35595140023SAndrea Di Biagio     return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
35695140023SAndrea Di Biagio 
35795140023SAndrea Di Biagio   if (Rec->isSubClassOf("CheckPseudo"))
35895140023SAndrea Di Biagio     return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
35995140023SAndrea Di Biagio 
36095140023SAndrea Di Biagio   if (Rec->isSubClassOf("CheckOpcode"))
36195140023SAndrea Di Biagio     return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
36295140023SAndrea Di Biagio 
36395140023SAndrea Di Biagio   if (Rec->isSubClassOf("CheckAll"))
36495140023SAndrea Di Biagio     return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
36595140023SAndrea Di Biagio                                    /* AllOf */ true);
36695140023SAndrea Di Biagio 
36795140023SAndrea Di Biagio   if (Rec->isSubClassOf("CheckAny"))
36895140023SAndrea Di Biagio     return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
36995140023SAndrea Di Biagio                                    /* AllOf */ false);
37095140023SAndrea Di Biagio 
3718a7ca143SEvgeny Leviant   if (Rec->isSubClassOf("CheckFunctionPredicate")) {
37295140023SAndrea Di Biagio     return expandCheckFunctionPredicate(
37395140023SAndrea Di Biagio         OS, Rec->getValueAsString("MCInstFnName"),
37495140023SAndrea Di Biagio         Rec->getValueAsString("MachineInstrFnName"));
3758a7ca143SEvgeny Leviant   }
3768a7ca143SEvgeny Leviant 
3778a7ca143SEvgeny Leviant   if (Rec->isSubClassOf("CheckFunctionPredicateWithTII")) {
3788a7ca143SEvgeny Leviant     return expandCheckFunctionPredicateWithTII(
3798a7ca143SEvgeny Leviant         OS, Rec->getValueAsString("MCInstFnName"),
3808a7ca143SEvgeny Leviant         Rec->getValueAsString("MachineInstrFnName"),
3818a7ca143SEvgeny Leviant         Rec->getValueAsString("TIIPtrName"));
3828a7ca143SEvgeny Leviant   }
38395140023SAndrea Di Biagio 
38495140023SAndrea Di Biagio   if (Rec->isSubClassOf("CheckNonPortable"))
38595140023SAndrea Di Biagio     return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
38695140023SAndrea Di Biagio 
38795140023SAndrea Di Biagio   if (Rec->isSubClassOf("TIIPredicate"))
3889eaf5aa0SAndrea Di Biagio     return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
38995140023SAndrea Di Biagio 
39095140023SAndrea Di Biagio   llvm_unreachable("No known rules to expand this MCInstPredicate");
39195140023SAndrea Di Biagio }
39295140023SAndrea Di Biagio 
expandHeader(raw_ostream & OS,const STIPredicateFunction & Fn)3938b6c314bSAndrea Di Biagio void STIPredicateExpander::expandHeader(raw_ostream &OS,
3948b6c314bSAndrea Di Biagio                                         const STIPredicateFunction &Fn) {
3958b6c314bSAndrea Di Biagio   const Record *Rec = Fn.getDeclaration();
3968b6c314bSAndrea Di Biagio   StringRef FunctionName = Rec->getValueAsString("Name");
3978b6c314bSAndrea Di Biagio 
3988b6c314bSAndrea Di Biagio   OS.indent(getIndentLevel() * 2);
3998b6c314bSAndrea Di Biagio   OS << "bool ";
4008b6c314bSAndrea Di Biagio   if (shouldExpandDefinition())
4018b6c314bSAndrea Di Biagio     OS << getClassPrefix() << "::";
4028b6c314bSAndrea Di Biagio   OS << FunctionName << "(";
4038b6c314bSAndrea Di Biagio   if (shouldExpandForMC())
4048b6c314bSAndrea Di Biagio     OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";
4058b6c314bSAndrea Di Biagio   else
4068b6c314bSAndrea Di Biagio     OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
4078b6c314bSAndrea Di Biagio   if (Rec->getValueAsBit("UpdatesOpcodeMask"))
4088b6c314bSAndrea Di Biagio     OS << ", APInt &Mask";
4098b6c314bSAndrea Di Biagio   OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
4108b6c314bSAndrea Di Biagio   if (shouldExpandDefinition()) {
4118b6c314bSAndrea Di Biagio     OS << "{\n";
4128b6c314bSAndrea Di Biagio     return;
4138b6c314bSAndrea Di Biagio   }
4148b6c314bSAndrea Di Biagio 
4158b6c314bSAndrea Di Biagio   if (Rec->getValueAsBit("OverridesBaseClassMember"))
4168b6c314bSAndrea Di Biagio     OS << "override";
4178b6c314bSAndrea Di Biagio   OS << ";\n";
4188b6c314bSAndrea Di Biagio }
4198b6c314bSAndrea Di Biagio 
expandPrologue(raw_ostream & OS,const STIPredicateFunction & Fn)4208b6c314bSAndrea Di Biagio void STIPredicateExpander::expandPrologue(raw_ostream &OS,
4218b6c314bSAndrea Di Biagio                                           const STIPredicateFunction &Fn) {
4228b6c314bSAndrea Di Biagio   RecVec Delegates = Fn.getDeclaration()->getValueAsListOfDefs("Delegates");
4238b6c314bSAndrea Di Biagio   bool UpdatesOpcodeMask =
4248b6c314bSAndrea Di Biagio       Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
4258b6c314bSAndrea Di Biagio 
4268b6c314bSAndrea Di Biagio   increaseIndentLevel();
4278b6c314bSAndrea Di Biagio   unsigned IndentLevel = getIndentLevel();
4288b6c314bSAndrea Di Biagio   for (const Record *Delegate : Delegates) {
4298b6c314bSAndrea Di Biagio     OS.indent(IndentLevel * 2);
4308b6c314bSAndrea Di Biagio     OS << "if (" << Delegate->getValueAsString("Name") << "(MI";
4318b6c314bSAndrea Di Biagio     if (UpdatesOpcodeMask)
4328b6c314bSAndrea Di Biagio       OS << ", Mask";
4338b6c314bSAndrea Di Biagio     if (shouldExpandForMC())
4348b6c314bSAndrea Di Biagio       OS << ", ProcessorID";
4358b6c314bSAndrea Di Biagio     OS << "))\n";
4368b6c314bSAndrea Di Biagio     OS.indent((1 + IndentLevel) * 2);
4378b6c314bSAndrea Di Biagio     OS << "return true;\n\n";
4388b6c314bSAndrea Di Biagio   }
4398b6c314bSAndrea Di Biagio 
4408b6c314bSAndrea Di Biagio   if (shouldExpandForMC())
4418b6c314bSAndrea Di Biagio     return;
4428b6c314bSAndrea Di Biagio 
4438b6c314bSAndrea Di Biagio   OS.indent(IndentLevel * 2);
4448b6c314bSAndrea Di Biagio   OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
4458b6c314bSAndrea Di Biagio }
4468b6c314bSAndrea Di Biagio 
expandOpcodeGroup(raw_ostream & OS,const OpcodeGroup & Group,bool ShouldUpdateOpcodeMask)4478b6c314bSAndrea Di Biagio void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS, const OpcodeGroup &Group,
4488b6c314bSAndrea Di Biagio                                              bool ShouldUpdateOpcodeMask) {
4498b6c314bSAndrea Di Biagio   const OpcodeInfo &OI = Group.getOpcodeInfo();
4508b6c314bSAndrea Di Biagio   for (const PredicateInfo &PI : OI.getPredicates()) {
4518b6c314bSAndrea Di Biagio     const APInt &ProcModelMask = PI.ProcModelMask;
4528b6c314bSAndrea Di Biagio     bool FirstProcID = true;
4538b6c314bSAndrea Di Biagio     for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {
4548b6c314bSAndrea Di Biagio       if (!ProcModelMask[I])
4558b6c314bSAndrea Di Biagio         continue;
4568b6c314bSAndrea Di Biagio 
4578b6c314bSAndrea Di Biagio       if (FirstProcID) {
4588b6c314bSAndrea Di Biagio         OS.indent(getIndentLevel() * 2);
4598b6c314bSAndrea Di Biagio         OS << "if (ProcessorID == " << I;
4608b6c314bSAndrea Di Biagio       } else {
4618b6c314bSAndrea Di Biagio         OS << " || ProcessorID == " << I;
4628b6c314bSAndrea Di Biagio       }
4638b6c314bSAndrea Di Biagio       FirstProcID = false;
4648b6c314bSAndrea Di Biagio     }
4658b6c314bSAndrea Di Biagio 
4668b6c314bSAndrea Di Biagio     OS << ") {\n";
4678b6c314bSAndrea Di Biagio 
4688b6c314bSAndrea Di Biagio     increaseIndentLevel();
4698b6c314bSAndrea Di Biagio     OS.indent(getIndentLevel() * 2);
4708b6c314bSAndrea Di Biagio     if (ShouldUpdateOpcodeMask) {
471*a9bceb2bSJay Foad       if (PI.OperandMask.isZero())
4728b6c314bSAndrea Di Biagio         OS << "Mask.clearAllBits();\n";
4738b6c314bSAndrea Di Biagio       else
4748b6c314bSAndrea Di Biagio         OS << "Mask = " << PI.OperandMask << ";\n";
4758b6c314bSAndrea Di Biagio       OS.indent(getIndentLevel() * 2);
4768b6c314bSAndrea Di Biagio     }
4778b6c314bSAndrea Di Biagio     OS << "return ";
4788b6c314bSAndrea Di Biagio     expandPredicate(OS, PI.Predicate);
4798b6c314bSAndrea Di Biagio     OS << ";\n";
4808b6c314bSAndrea Di Biagio     decreaseIndentLevel();
4818b6c314bSAndrea Di Biagio     OS.indent(getIndentLevel() * 2);
4828b6c314bSAndrea Di Biagio     OS << "}\n";
4838b6c314bSAndrea Di Biagio   }
4848b6c314bSAndrea Di Biagio }
4858b6c314bSAndrea Di Biagio 
expandBody(raw_ostream & OS,const STIPredicateFunction & Fn)4868b6c314bSAndrea Di Biagio void STIPredicateExpander::expandBody(raw_ostream &OS,
4878b6c314bSAndrea Di Biagio                                       const STIPredicateFunction &Fn) {
4888b6c314bSAndrea Di Biagio   bool UpdatesOpcodeMask =
4898b6c314bSAndrea Di Biagio       Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
4908b6c314bSAndrea Di Biagio 
4918b6c314bSAndrea Di Biagio   unsigned IndentLevel = getIndentLevel();
4928b6c314bSAndrea Di Biagio   OS.indent(IndentLevel * 2);
4938b6c314bSAndrea Di Biagio   OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
4948b6c314bSAndrea Di Biagio   OS.indent(IndentLevel * 2);
4958b6c314bSAndrea Di Biagio   OS << "default:\n";
4968b6c314bSAndrea Di Biagio   OS.indent(IndentLevel * 2);
4978b6c314bSAndrea Di Biagio   OS << "  break;";
4988b6c314bSAndrea Di Biagio 
4998b6c314bSAndrea Di Biagio   for (const OpcodeGroup &Group : Fn.getGroups()) {
5008b6c314bSAndrea Di Biagio     for (const Record *Opcode : Group.getOpcodes()) {
5018b6c314bSAndrea Di Biagio       OS << '\n';
5028b6c314bSAndrea Di Biagio       OS.indent(IndentLevel * 2);
5038b6c314bSAndrea Di Biagio       OS << "case " << getTargetName() << "::" << Opcode->getName() << ":";
5048b6c314bSAndrea Di Biagio     }
5058b6c314bSAndrea Di Biagio 
5068b6c314bSAndrea Di Biagio     OS << '\n';
5078b6c314bSAndrea Di Biagio     increaseIndentLevel();
5088b6c314bSAndrea Di Biagio     expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);
5098b6c314bSAndrea Di Biagio 
5108b6c314bSAndrea Di Biagio     OS.indent(getIndentLevel() * 2);
5118b6c314bSAndrea Di Biagio     OS << "break;\n";
5128b6c314bSAndrea Di Biagio     decreaseIndentLevel();
5138b6c314bSAndrea Di Biagio   }
5148b6c314bSAndrea Di Biagio 
5158b6c314bSAndrea Di Biagio   OS.indent(IndentLevel * 2);
5168b6c314bSAndrea Di Biagio   OS << "}\n";
5178b6c314bSAndrea Di Biagio }
5188b6c314bSAndrea Di Biagio 
expandEpilogue(raw_ostream & OS,const STIPredicateFunction & Fn)5198b6c314bSAndrea Di Biagio void STIPredicateExpander::expandEpilogue(raw_ostream &OS,
5208b6c314bSAndrea Di Biagio                                           const STIPredicateFunction &Fn) {
5218b6c314bSAndrea Di Biagio   OS << '\n';
5228b6c314bSAndrea Di Biagio   OS.indent(getIndentLevel() * 2);
5238b6c314bSAndrea Di Biagio   OS << "return ";
5248b6c314bSAndrea Di Biagio   expandPredicate(OS, Fn.getDefaultReturnPredicate());
5258b6c314bSAndrea Di Biagio   OS << ";\n";
5268b6c314bSAndrea Di Biagio 
5278b6c314bSAndrea Di Biagio   decreaseIndentLevel();
5288b6c314bSAndrea Di Biagio   OS.indent(getIndentLevel() * 2);
5298b6c314bSAndrea Di Biagio   StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");
5308b6c314bSAndrea Di Biagio   OS << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
5318b6c314bSAndrea Di Biagio }
5328b6c314bSAndrea Di Biagio 
expandSTIPredicate(raw_ostream & OS,const STIPredicateFunction & Fn)5338b6c314bSAndrea Di Biagio void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
5348b6c314bSAndrea Di Biagio                                               const STIPredicateFunction &Fn) {
5358b6c314bSAndrea Di Biagio   const Record *Rec = Fn.getDeclaration();
5368b6c314bSAndrea Di Biagio   if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))
5378b6c314bSAndrea Di Biagio     return;
5388b6c314bSAndrea Di Biagio 
5398b6c314bSAndrea Di Biagio   expandHeader(OS, Fn);
5408b6c314bSAndrea Di Biagio   if (shouldExpandDefinition()) {
5418b6c314bSAndrea Di Biagio     expandPrologue(OS, Fn);
5428b6c314bSAndrea Di Biagio     expandBody(OS, Fn);
5438b6c314bSAndrea Di Biagio     expandEpilogue(OS, Fn);
5448b6c314bSAndrea Di Biagio   }
5458b6c314bSAndrea Di Biagio }
5468b6c314bSAndrea Di Biagio 
54795140023SAndrea Di Biagio } // namespace llvm
548