10b57cec5SDimitry Andric //===--------------------- PredicateExpander.cpp --------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric /// Functionalities used by the Tablegen backends to expand machine predicates.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "PredicateExpander.h"
140b57cec5SDimitry Andric #include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric namespace llvm {
170b57cec5SDimitry Andric
expandTrue(raw_ostream & OS)180b57cec5SDimitry Andric void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
expandFalse(raw_ostream & OS)190b57cec5SDimitry Andric void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
200b57cec5SDimitry Andric
expandCheckImmOperand(raw_ostream & OS,int OpIndex,int ImmVal,StringRef FunctionMapper)210b57cec5SDimitry Andric void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
220b57cec5SDimitry Andric int ImmVal,
230b57cec5SDimitry Andric StringRef FunctionMapper) {
240b57cec5SDimitry Andric if (!FunctionMapper.empty())
250b57cec5SDimitry Andric OS << FunctionMapper << "(";
260b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
270b57cec5SDimitry Andric << ").getImm()";
280b57cec5SDimitry Andric if (!FunctionMapper.empty())
290b57cec5SDimitry Andric OS << ")";
300b57cec5SDimitry Andric OS << (shouldNegate() ? " != " : " == ") << ImmVal;
310b57cec5SDimitry Andric }
320b57cec5SDimitry Andric
expandCheckImmOperand(raw_ostream & OS,int OpIndex,StringRef ImmVal,StringRef FunctionMapper)330b57cec5SDimitry Andric void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
340b57cec5SDimitry Andric StringRef ImmVal,
350b57cec5SDimitry Andric StringRef FunctionMapper) {
360b57cec5SDimitry Andric if (ImmVal.empty())
370b57cec5SDimitry Andric expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric if (!FunctionMapper.empty())
400b57cec5SDimitry Andric OS << FunctionMapper << "(";
410b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
420b57cec5SDimitry Andric << ").getImm()";
430b57cec5SDimitry Andric if (!FunctionMapper.empty())
440b57cec5SDimitry Andric OS << ")";
450b57cec5SDimitry Andric OS << (shouldNegate() ? " != " : " == ") << ImmVal;
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric
expandCheckImmOperandSimple(raw_ostream & OS,int OpIndex,StringRef FunctionMapper)480b57cec5SDimitry Andric void PredicateExpander::expandCheckImmOperandSimple(raw_ostream &OS,
490b57cec5SDimitry Andric int OpIndex,
500b57cec5SDimitry Andric StringRef FunctionMapper) {
510b57cec5SDimitry Andric if (shouldNegate())
520b57cec5SDimitry Andric OS << "!";
530b57cec5SDimitry Andric if (!FunctionMapper.empty())
540b57cec5SDimitry Andric OS << FunctionMapper << "(";
550b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
560b57cec5SDimitry Andric << ").getImm()";
570b57cec5SDimitry Andric if (!FunctionMapper.empty())
580b57cec5SDimitry Andric OS << ")";
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric
expandCheckRegOperand(raw_ostream & OS,int OpIndex,const Record * Reg,StringRef FunctionMapper)610b57cec5SDimitry Andric void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
620b57cec5SDimitry Andric const Record *Reg,
630b57cec5SDimitry Andric StringRef FunctionMapper) {
640b57cec5SDimitry Andric assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric if (!FunctionMapper.empty())
670b57cec5SDimitry Andric OS << FunctionMapper << "(";
680b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
690b57cec5SDimitry Andric << ").getReg()";
700b57cec5SDimitry Andric if (!FunctionMapper.empty())
710b57cec5SDimitry Andric OS << ")";
720b57cec5SDimitry Andric OS << (shouldNegate() ? " != " : " == ");
730b57cec5SDimitry Andric const StringRef Str = Reg->getValueAsString("Namespace");
740b57cec5SDimitry Andric if (!Str.empty())
750b57cec5SDimitry Andric OS << Str << "::";
760b57cec5SDimitry Andric OS << Reg->getName();
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric
expandCheckRegOperandSimple(raw_ostream & OS,int OpIndex,StringRef FunctionMapper)800b57cec5SDimitry Andric void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
810b57cec5SDimitry Andric int OpIndex,
820b57cec5SDimitry Andric StringRef FunctionMapper) {
830b57cec5SDimitry Andric if (shouldNegate())
840b57cec5SDimitry Andric OS << "!";
850b57cec5SDimitry Andric if (!FunctionMapper.empty())
860b57cec5SDimitry Andric OS << FunctionMapper << "(";
870b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
880b57cec5SDimitry Andric << ").getReg()";
890b57cec5SDimitry Andric if (!FunctionMapper.empty())
900b57cec5SDimitry Andric OS << ")";
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric
expandCheckInvalidRegOperand(raw_ostream & OS,int OpIndex)930b57cec5SDimitry Andric void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
940b57cec5SDimitry Andric int OpIndex) {
950b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
960b57cec5SDimitry Andric << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric
expandCheckSameRegOperand(raw_ostream & OS,int First,int Second)990b57cec5SDimitry Andric void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,
1000b57cec5SDimitry Andric int Second) {
1010b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
1020b57cec5SDimitry Andric << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
1030b57cec5SDimitry Andric << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric
expandCheckNumOperands(raw_ostream & OS,int NumOps)1060b57cec5SDimitry Andric void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
1070b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
1080b57cec5SDimitry Andric << (shouldNegate() ? "!= " : "== ") << NumOps;
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric
expandCheckOpcode(raw_ostream & OS,const Record * Inst)1110b57cec5SDimitry Andric void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
1120b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
1130b57cec5SDimitry Andric << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
1140b57cec5SDimitry Andric << "::" << Inst->getName();
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric
expandCheckOpcode(raw_ostream & OS,const RecVec & Opcodes)1170b57cec5SDimitry Andric void PredicateExpander::expandCheckOpcode(raw_ostream &OS,
1180b57cec5SDimitry Andric const RecVec &Opcodes) {
1190b57cec5SDimitry Andric assert(!Opcodes.empty() && "Expected at least one opcode to check!");
1200b57cec5SDimitry Andric bool First = true;
1210b57cec5SDimitry Andric
1220b57cec5SDimitry Andric if (Opcodes.size() == 1) {
1230b57cec5SDimitry Andric OS << "( ";
1240b57cec5SDimitry Andric expandCheckOpcode(OS, Opcodes[0]);
1250b57cec5SDimitry Andric OS << " )";
1260b57cec5SDimitry Andric return;
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric
1290b57cec5SDimitry Andric OS << '(';
1300b57cec5SDimitry Andric increaseIndentLevel();
1310b57cec5SDimitry Andric for (const Record *Rec : Opcodes) {
1320b57cec5SDimitry Andric OS << '\n';
1330b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
1340b57cec5SDimitry Andric if (!First)
1350b57cec5SDimitry Andric OS << (shouldNegate() ? "&& " : "|| ");
1360b57cec5SDimitry Andric
1370b57cec5SDimitry Andric expandCheckOpcode(OS, Rec);
1380b57cec5SDimitry Andric First = false;
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric
1410b57cec5SDimitry Andric OS << '\n';
1420b57cec5SDimitry Andric decreaseIndentLevel();
1430b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
1440b57cec5SDimitry Andric OS << ')';
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric
expandCheckPseudo(raw_ostream & OS,const RecVec & Opcodes)1470b57cec5SDimitry Andric void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
1480b57cec5SDimitry Andric const RecVec &Opcodes) {
1490b57cec5SDimitry Andric if (shouldExpandForMC())
1500b57cec5SDimitry Andric expandFalse(OS);
1510b57cec5SDimitry Andric else
1520b57cec5SDimitry Andric expandCheckOpcode(OS, Opcodes);
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric
expandPredicateSequence(raw_ostream & OS,const RecVec & Sequence,bool IsCheckAll)1550b57cec5SDimitry Andric void PredicateExpander::expandPredicateSequence(raw_ostream &OS,
1560b57cec5SDimitry Andric const RecVec &Sequence,
1570b57cec5SDimitry Andric bool IsCheckAll) {
1580b57cec5SDimitry Andric assert(!Sequence.empty() && "Found an invalid empty predicate set!");
1590b57cec5SDimitry Andric if (Sequence.size() == 1)
1600b57cec5SDimitry Andric return expandPredicate(OS, Sequence[0]);
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andric // Okay, there is more than one predicate in the set.
1630b57cec5SDimitry Andric bool First = true;
1640b57cec5SDimitry Andric OS << (shouldNegate() ? "!(" : "(");
1650b57cec5SDimitry Andric increaseIndentLevel();
1660b57cec5SDimitry Andric
1670b57cec5SDimitry Andric bool OldValue = shouldNegate();
1680b57cec5SDimitry Andric setNegatePredicate(false);
1690b57cec5SDimitry Andric for (const Record *Rec : Sequence) {
1700b57cec5SDimitry Andric OS << '\n';
1710b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
1720b57cec5SDimitry Andric if (!First)
1730b57cec5SDimitry Andric OS << (IsCheckAll ? "&& " : "|| ");
1740b57cec5SDimitry Andric expandPredicate(OS, Rec);
1750b57cec5SDimitry Andric First = false;
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric OS << '\n';
1780b57cec5SDimitry Andric decreaseIndentLevel();
1790b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
1800b57cec5SDimitry Andric OS << ')';
1810b57cec5SDimitry Andric setNegatePredicate(OldValue);
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric
expandTIIFunctionCall(raw_ostream & OS,StringRef MethodName)1840b57cec5SDimitry Andric void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,
1850b57cec5SDimitry Andric StringRef MethodName) {
1860b57cec5SDimitry Andric OS << (shouldNegate() ? "!" : "");
1870b57cec5SDimitry Andric OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");
1880b57cec5SDimitry Andric OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric
expandCheckIsRegOperand(raw_ostream & OS,int OpIndex)1910b57cec5SDimitry Andric void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
1920b57cec5SDimitry Andric OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
1930b57cec5SDimitry Andric << "getOperand(" << OpIndex << ").isReg() ";
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric
expandCheckIsImmOperand(raw_ostream & OS,int OpIndex)1960b57cec5SDimitry Andric void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
1970b57cec5SDimitry Andric OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
1980b57cec5SDimitry Andric << "getOperand(" << OpIndex << ").isImm() ";
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric
expandCheckFunctionPredicateWithTII(raw_ostream & OS,StringRef MCInstFn,StringRef MachineInstrFn,StringRef TIIPtr)201*af732203SDimitry Andric void PredicateExpander::expandCheckFunctionPredicateWithTII(
202*af732203SDimitry Andric raw_ostream &OS, StringRef MCInstFn, StringRef MachineInstrFn,
203*af732203SDimitry Andric StringRef TIIPtr) {
204*af732203SDimitry Andric if (!shouldExpandForMC()) {
205*af732203SDimitry Andric OS << (TIIPtr.empty() ? "TII" : TIIPtr) << "->" << MachineInstrFn;
206*af732203SDimitry Andric OS << (isByRef() ? "(MI)" : "(*MI)");
207*af732203SDimitry Andric return;
208*af732203SDimitry Andric }
209*af732203SDimitry Andric
210*af732203SDimitry Andric OS << MCInstFn << (isByRef() ? "(MI" : "(*MI") << ", MCII)";
211*af732203SDimitry Andric }
212*af732203SDimitry Andric
expandCheckFunctionPredicate(raw_ostream & OS,StringRef MCInstFn,StringRef MachineInstrFn)2130b57cec5SDimitry Andric void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
2140b57cec5SDimitry Andric StringRef MCInstFn,
2150b57cec5SDimitry Andric StringRef MachineInstrFn) {
2160b57cec5SDimitry Andric OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
2170b57cec5SDimitry Andric << (isByRef() ? "(MI)" : "(*MI)");
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric
expandCheckNonPortable(raw_ostream & OS,StringRef Code)2200b57cec5SDimitry Andric void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
2210b57cec5SDimitry Andric StringRef Code) {
2220b57cec5SDimitry Andric if (shouldExpandForMC())
2230b57cec5SDimitry Andric return expandFalse(OS);
2240b57cec5SDimitry Andric
2250b57cec5SDimitry Andric OS << '(' << Code << ')';
2260b57cec5SDimitry Andric }
2270b57cec5SDimitry Andric
expandReturnStatement(raw_ostream & OS,const Record * Rec)2280b57cec5SDimitry Andric void PredicateExpander::expandReturnStatement(raw_ostream &OS,
2290b57cec5SDimitry Andric const Record *Rec) {
2300b57cec5SDimitry Andric std::string Buffer;
2310b57cec5SDimitry Andric raw_string_ostream SS(Buffer);
2320b57cec5SDimitry Andric
2330b57cec5SDimitry Andric SS << "return ";
2340b57cec5SDimitry Andric expandPredicate(SS, Rec);
2350b57cec5SDimitry Andric SS << ";";
2360b57cec5SDimitry Andric SS.flush();
2370b57cec5SDimitry Andric OS << Buffer;
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric
expandOpcodeSwitchCase(raw_ostream & OS,const Record * Rec)2400b57cec5SDimitry Andric void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
2410b57cec5SDimitry Andric const Record *Rec) {
2420b57cec5SDimitry Andric const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
2430b57cec5SDimitry Andric for (const Record *Opcode : Opcodes) {
2440b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
2450b57cec5SDimitry Andric OS << "case " << Opcode->getValueAsString("Namespace")
2460b57cec5SDimitry Andric << "::" << Opcode->getName() << ":\n";
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric
2490b57cec5SDimitry Andric increaseIndentLevel();
2500b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
2510b57cec5SDimitry Andric expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
2520b57cec5SDimitry Andric decreaseIndentLevel();
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric
expandOpcodeSwitchStatement(raw_ostream & OS,const RecVec & Cases,const Record * Default)2550b57cec5SDimitry Andric void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,
2560b57cec5SDimitry Andric const RecVec &Cases,
2570b57cec5SDimitry Andric const Record *Default) {
2580b57cec5SDimitry Andric std::string Buffer;
2590b57cec5SDimitry Andric raw_string_ostream SS(Buffer);
2600b57cec5SDimitry Andric
2610b57cec5SDimitry Andric SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
2620b57cec5SDimitry Andric for (const Record *Rec : Cases) {
2630b57cec5SDimitry Andric expandOpcodeSwitchCase(SS, Rec);
2640b57cec5SDimitry Andric SS << '\n';
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric
2670b57cec5SDimitry Andric // Expand the default case.
2680b57cec5SDimitry Andric SS.indent(getIndentLevel() * 2);
2690b57cec5SDimitry Andric SS << "default:\n";
2700b57cec5SDimitry Andric
2710b57cec5SDimitry Andric increaseIndentLevel();
2720b57cec5SDimitry Andric SS.indent(getIndentLevel() * 2);
2730b57cec5SDimitry Andric expandStatement(SS, Default);
2740b57cec5SDimitry Andric decreaseIndentLevel();
2750b57cec5SDimitry Andric SS << '\n';
2760b57cec5SDimitry Andric
2770b57cec5SDimitry Andric SS.indent(getIndentLevel() * 2);
2780b57cec5SDimitry Andric SS << "} // end of switch-stmt";
2790b57cec5SDimitry Andric SS.flush();
2800b57cec5SDimitry Andric OS << Buffer;
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric
expandStatement(raw_ostream & OS,const Record * Rec)2830b57cec5SDimitry Andric void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
2840b57cec5SDimitry Andric // Assume that padding has been added by the caller.
2850b57cec5SDimitry Andric if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
2860b57cec5SDimitry Andric expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
2870b57cec5SDimitry Andric Rec->getValueAsDef("DefaultCase"));
2880b57cec5SDimitry Andric return;
2890b57cec5SDimitry Andric }
2900b57cec5SDimitry Andric
2910b57cec5SDimitry Andric if (Rec->isSubClassOf("MCReturnStatement")) {
2920b57cec5SDimitry Andric expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
2930b57cec5SDimitry Andric return;
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric
2960b57cec5SDimitry Andric llvm_unreachable("No known rules to expand this MCStatement");
2970b57cec5SDimitry Andric }
2980b57cec5SDimitry Andric
expandPredicate(raw_ostream & OS,const Record * Rec)2990b57cec5SDimitry Andric void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
3000b57cec5SDimitry Andric // Assume that padding has been added by the caller.
3010b57cec5SDimitry Andric if (Rec->isSubClassOf("MCTrue")) {
3020b57cec5SDimitry Andric if (shouldNegate())
3030b57cec5SDimitry Andric return expandFalse(OS);
3040b57cec5SDimitry Andric return expandTrue(OS);
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric
3070b57cec5SDimitry Andric if (Rec->isSubClassOf("MCFalse")) {
3080b57cec5SDimitry Andric if (shouldNegate())
3090b57cec5SDimitry Andric return expandTrue(OS);
3100b57cec5SDimitry Andric return expandFalse(OS);
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric
3130b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckNot")) {
3140b57cec5SDimitry Andric flipNegatePredicate();
3150b57cec5SDimitry Andric expandPredicate(OS, Rec->getValueAsDef("Pred"));
3160b57cec5SDimitry Andric flipNegatePredicate();
3170b57cec5SDimitry Andric return;
3180b57cec5SDimitry Andric }
3190b57cec5SDimitry Andric
3200b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckIsRegOperand"))
3210b57cec5SDimitry Andric return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
3220b57cec5SDimitry Andric
3230b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckIsImmOperand"))
3240b57cec5SDimitry Andric return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
3250b57cec5SDimitry Andric
3260b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckRegOperand"))
3270b57cec5SDimitry Andric return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
3280b57cec5SDimitry Andric Rec->getValueAsDef("Reg"),
3290b57cec5SDimitry Andric Rec->getValueAsString("FunctionMapper"));
3300b57cec5SDimitry Andric
3310b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckRegOperandSimple"))
3320b57cec5SDimitry Andric return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
3330b57cec5SDimitry Andric Rec->getValueAsString("FunctionMapper"));
3340b57cec5SDimitry Andric
3350b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckInvalidRegOperand"))
3360b57cec5SDimitry Andric return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
3370b57cec5SDimitry Andric
3380b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckImmOperand"))
3390b57cec5SDimitry Andric return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
3400b57cec5SDimitry Andric Rec->getValueAsInt("ImmVal"),
3410b57cec5SDimitry Andric Rec->getValueAsString("FunctionMapper"));
3420b57cec5SDimitry Andric
3430b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckImmOperand_s"))
3440b57cec5SDimitry Andric return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
3450b57cec5SDimitry Andric Rec->getValueAsString("ImmVal"),
3460b57cec5SDimitry Andric Rec->getValueAsString("FunctionMapper"));
3470b57cec5SDimitry Andric
3480b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckImmOperandSimple"))
3490b57cec5SDimitry Andric return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
3500b57cec5SDimitry Andric Rec->getValueAsString("FunctionMapper"));
3510b57cec5SDimitry Andric
3520b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckSameRegOperand"))
3530b57cec5SDimitry Andric return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
3540b57cec5SDimitry Andric Rec->getValueAsInt("SecondIndex"));
3550b57cec5SDimitry Andric
3560b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckNumOperands"))
3570b57cec5SDimitry Andric return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
3580b57cec5SDimitry Andric
3590b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckPseudo"))
3600b57cec5SDimitry Andric return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
3610b57cec5SDimitry Andric
3620b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckOpcode"))
3630b57cec5SDimitry Andric return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
3640b57cec5SDimitry Andric
3650b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckAll"))
3660b57cec5SDimitry Andric return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
3670b57cec5SDimitry Andric /* AllOf */ true);
3680b57cec5SDimitry Andric
3690b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckAny"))
3700b57cec5SDimitry Andric return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
3710b57cec5SDimitry Andric /* AllOf */ false);
3720b57cec5SDimitry Andric
373*af732203SDimitry Andric if (Rec->isSubClassOf("CheckFunctionPredicate")) {
3740b57cec5SDimitry Andric return expandCheckFunctionPredicate(
3750b57cec5SDimitry Andric OS, Rec->getValueAsString("MCInstFnName"),
3760b57cec5SDimitry Andric Rec->getValueAsString("MachineInstrFnName"));
377*af732203SDimitry Andric }
378*af732203SDimitry Andric
379*af732203SDimitry Andric if (Rec->isSubClassOf("CheckFunctionPredicateWithTII")) {
380*af732203SDimitry Andric return expandCheckFunctionPredicateWithTII(
381*af732203SDimitry Andric OS, Rec->getValueAsString("MCInstFnName"),
382*af732203SDimitry Andric Rec->getValueAsString("MachineInstrFnName"),
383*af732203SDimitry Andric Rec->getValueAsString("TIIPtrName"));
384*af732203SDimitry Andric }
3850b57cec5SDimitry Andric
3860b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckNonPortable"))
3870b57cec5SDimitry Andric return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
3880b57cec5SDimitry Andric
3890b57cec5SDimitry Andric if (Rec->isSubClassOf("TIIPredicate"))
3900b57cec5SDimitry Andric return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
3910b57cec5SDimitry Andric
3920b57cec5SDimitry Andric llvm_unreachable("No known rules to expand this MCInstPredicate");
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric
expandHeader(raw_ostream & OS,const STIPredicateFunction & Fn)3950b57cec5SDimitry Andric void STIPredicateExpander::expandHeader(raw_ostream &OS,
3960b57cec5SDimitry Andric const STIPredicateFunction &Fn) {
3970b57cec5SDimitry Andric const Record *Rec = Fn.getDeclaration();
3980b57cec5SDimitry Andric StringRef FunctionName = Rec->getValueAsString("Name");
3990b57cec5SDimitry Andric
4000b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
4010b57cec5SDimitry Andric OS << "bool ";
4020b57cec5SDimitry Andric if (shouldExpandDefinition())
4030b57cec5SDimitry Andric OS << getClassPrefix() << "::";
4040b57cec5SDimitry Andric OS << FunctionName << "(";
4050b57cec5SDimitry Andric if (shouldExpandForMC())
4060b57cec5SDimitry Andric OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";
4070b57cec5SDimitry Andric else
4080b57cec5SDimitry Andric OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
4090b57cec5SDimitry Andric if (Rec->getValueAsBit("UpdatesOpcodeMask"))
4100b57cec5SDimitry Andric OS << ", APInt &Mask";
4110b57cec5SDimitry Andric OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
4120b57cec5SDimitry Andric if (shouldExpandDefinition()) {
4130b57cec5SDimitry Andric OS << "{\n";
4140b57cec5SDimitry Andric return;
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric
4170b57cec5SDimitry Andric if (Rec->getValueAsBit("OverridesBaseClassMember"))
4180b57cec5SDimitry Andric OS << "override";
4190b57cec5SDimitry Andric OS << ";\n";
4200b57cec5SDimitry Andric }
4210b57cec5SDimitry Andric
expandPrologue(raw_ostream & OS,const STIPredicateFunction & Fn)4220b57cec5SDimitry Andric void STIPredicateExpander::expandPrologue(raw_ostream &OS,
4230b57cec5SDimitry Andric const STIPredicateFunction &Fn) {
4240b57cec5SDimitry Andric RecVec Delegates = Fn.getDeclaration()->getValueAsListOfDefs("Delegates");
4250b57cec5SDimitry Andric bool UpdatesOpcodeMask =
4260b57cec5SDimitry Andric Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
4270b57cec5SDimitry Andric
4280b57cec5SDimitry Andric increaseIndentLevel();
4290b57cec5SDimitry Andric unsigned IndentLevel = getIndentLevel();
4300b57cec5SDimitry Andric for (const Record *Delegate : Delegates) {
4310b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
4320b57cec5SDimitry Andric OS << "if (" << Delegate->getValueAsString("Name") << "(MI";
4330b57cec5SDimitry Andric if (UpdatesOpcodeMask)
4340b57cec5SDimitry Andric OS << ", Mask";
4350b57cec5SDimitry Andric if (shouldExpandForMC())
4360b57cec5SDimitry Andric OS << ", ProcessorID";
4370b57cec5SDimitry Andric OS << "))\n";
4380b57cec5SDimitry Andric OS.indent((1 + IndentLevel) * 2);
4390b57cec5SDimitry Andric OS << "return true;\n\n";
4400b57cec5SDimitry Andric }
4410b57cec5SDimitry Andric
4420b57cec5SDimitry Andric if (shouldExpandForMC())
4430b57cec5SDimitry Andric return;
4440b57cec5SDimitry Andric
4450b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
4460b57cec5SDimitry Andric OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric
expandOpcodeGroup(raw_ostream & OS,const OpcodeGroup & Group,bool ShouldUpdateOpcodeMask)4490b57cec5SDimitry Andric void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS, const OpcodeGroup &Group,
4500b57cec5SDimitry Andric bool ShouldUpdateOpcodeMask) {
4510b57cec5SDimitry Andric const OpcodeInfo &OI = Group.getOpcodeInfo();
4520b57cec5SDimitry Andric for (const PredicateInfo &PI : OI.getPredicates()) {
4530b57cec5SDimitry Andric const APInt &ProcModelMask = PI.ProcModelMask;
4540b57cec5SDimitry Andric bool FirstProcID = true;
4550b57cec5SDimitry Andric for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {
4560b57cec5SDimitry Andric if (!ProcModelMask[I])
4570b57cec5SDimitry Andric continue;
4580b57cec5SDimitry Andric
4590b57cec5SDimitry Andric if (FirstProcID) {
4600b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
4610b57cec5SDimitry Andric OS << "if (ProcessorID == " << I;
4620b57cec5SDimitry Andric } else {
4630b57cec5SDimitry Andric OS << " || ProcessorID == " << I;
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric FirstProcID = false;
4660b57cec5SDimitry Andric }
4670b57cec5SDimitry Andric
4680b57cec5SDimitry Andric OS << ") {\n";
4690b57cec5SDimitry Andric
4700b57cec5SDimitry Andric increaseIndentLevel();
4710b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
4720b57cec5SDimitry Andric if (ShouldUpdateOpcodeMask) {
4730b57cec5SDimitry Andric if (PI.OperandMask.isNullValue())
4740b57cec5SDimitry Andric OS << "Mask.clearAllBits();\n";
4750b57cec5SDimitry Andric else
4760b57cec5SDimitry Andric OS << "Mask = " << PI.OperandMask << ";\n";
4770b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
4780b57cec5SDimitry Andric }
4790b57cec5SDimitry Andric OS << "return ";
4800b57cec5SDimitry Andric expandPredicate(OS, PI.Predicate);
4810b57cec5SDimitry Andric OS << ";\n";
4820b57cec5SDimitry Andric decreaseIndentLevel();
4830b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
4840b57cec5SDimitry Andric OS << "}\n";
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric }
4870b57cec5SDimitry Andric
expandBody(raw_ostream & OS,const STIPredicateFunction & Fn)4880b57cec5SDimitry Andric void STIPredicateExpander::expandBody(raw_ostream &OS,
4890b57cec5SDimitry Andric const STIPredicateFunction &Fn) {
4900b57cec5SDimitry Andric bool UpdatesOpcodeMask =
4910b57cec5SDimitry Andric Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
4920b57cec5SDimitry Andric
4930b57cec5SDimitry Andric unsigned IndentLevel = getIndentLevel();
4940b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
4950b57cec5SDimitry Andric OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
4960b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
4970b57cec5SDimitry Andric OS << "default:\n";
4980b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
4990b57cec5SDimitry Andric OS << " break;";
5000b57cec5SDimitry Andric
5010b57cec5SDimitry Andric for (const OpcodeGroup &Group : Fn.getGroups()) {
5020b57cec5SDimitry Andric for (const Record *Opcode : Group.getOpcodes()) {
5030b57cec5SDimitry Andric OS << '\n';
5040b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
5050b57cec5SDimitry Andric OS << "case " << getTargetName() << "::" << Opcode->getName() << ":";
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric
5080b57cec5SDimitry Andric OS << '\n';
5090b57cec5SDimitry Andric increaseIndentLevel();
5100b57cec5SDimitry Andric expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);
5110b57cec5SDimitry Andric
5120b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
5130b57cec5SDimitry Andric OS << "break;\n";
5140b57cec5SDimitry Andric decreaseIndentLevel();
5150b57cec5SDimitry Andric }
5160b57cec5SDimitry Andric
5170b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
5180b57cec5SDimitry Andric OS << "}\n";
5190b57cec5SDimitry Andric }
5200b57cec5SDimitry Andric
expandEpilogue(raw_ostream & OS,const STIPredicateFunction & Fn)5210b57cec5SDimitry Andric void STIPredicateExpander::expandEpilogue(raw_ostream &OS,
5220b57cec5SDimitry Andric const STIPredicateFunction &Fn) {
5230b57cec5SDimitry Andric OS << '\n';
5240b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
5250b57cec5SDimitry Andric OS << "return ";
5260b57cec5SDimitry Andric expandPredicate(OS, Fn.getDefaultReturnPredicate());
5270b57cec5SDimitry Andric OS << ";\n";
5280b57cec5SDimitry Andric
5290b57cec5SDimitry Andric decreaseIndentLevel();
5300b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
5310b57cec5SDimitry Andric StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");
5320b57cec5SDimitry Andric OS << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
5330b57cec5SDimitry Andric }
5340b57cec5SDimitry Andric
expandSTIPredicate(raw_ostream & OS,const STIPredicateFunction & Fn)5350b57cec5SDimitry Andric void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
5360b57cec5SDimitry Andric const STIPredicateFunction &Fn) {
5370b57cec5SDimitry Andric const Record *Rec = Fn.getDeclaration();
5380b57cec5SDimitry Andric if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))
5390b57cec5SDimitry Andric return;
5400b57cec5SDimitry Andric
5410b57cec5SDimitry Andric expandHeader(OS, Fn);
5420b57cec5SDimitry Andric if (shouldExpandDefinition()) {
5430b57cec5SDimitry Andric expandPrologue(OS, Fn);
5440b57cec5SDimitry Andric expandBody(OS, Fn);
5450b57cec5SDimitry Andric expandEpilogue(OS, Fn);
5460b57cec5SDimitry Andric }
5470b57cec5SDimitry Andric }
5480b57cec5SDimitry Andric
5490b57cec5SDimitry Andric } // namespace llvm
550