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.
15fe013be4SDimitry Andric #include "llvm/TableGen/Record.h"
160b57cec5SDimitry Andric
170b57cec5SDimitry Andric namespace llvm {
180b57cec5SDimitry Andric
expandTrue(raw_ostream & OS)190b57cec5SDimitry Andric void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
expandFalse(raw_ostream & OS)200b57cec5SDimitry Andric void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
210b57cec5SDimitry Andric
expandCheckImmOperand(raw_ostream & OS,int OpIndex,int ImmVal,StringRef FunctionMapper)220b57cec5SDimitry Andric void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
230b57cec5SDimitry Andric int ImmVal,
240b57cec5SDimitry Andric StringRef FunctionMapper) {
250b57cec5SDimitry Andric if (!FunctionMapper.empty())
260b57cec5SDimitry Andric OS << FunctionMapper << "(";
270b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
280b57cec5SDimitry Andric << ").getImm()";
290b57cec5SDimitry Andric if (!FunctionMapper.empty())
300b57cec5SDimitry Andric OS << ")";
310b57cec5SDimitry Andric OS << (shouldNegate() ? " != " : " == ") << ImmVal;
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric
expandCheckImmOperand(raw_ostream & OS,int OpIndex,StringRef ImmVal,StringRef FunctionMapper)340b57cec5SDimitry Andric void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
350b57cec5SDimitry Andric StringRef ImmVal,
360b57cec5SDimitry Andric StringRef FunctionMapper) {
370b57cec5SDimitry Andric if (ImmVal.empty())
380b57cec5SDimitry Andric expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric if (!FunctionMapper.empty())
410b57cec5SDimitry Andric OS << FunctionMapper << "(";
420b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
430b57cec5SDimitry Andric << ").getImm()";
440b57cec5SDimitry Andric if (!FunctionMapper.empty())
450b57cec5SDimitry Andric OS << ")";
460b57cec5SDimitry Andric OS << (shouldNegate() ? " != " : " == ") << ImmVal;
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric
expandCheckImmOperandSimple(raw_ostream & OS,int OpIndex,StringRef FunctionMapper)490b57cec5SDimitry Andric void PredicateExpander::expandCheckImmOperandSimple(raw_ostream &OS,
500b57cec5SDimitry Andric int OpIndex,
510b57cec5SDimitry Andric StringRef FunctionMapper) {
520b57cec5SDimitry Andric if (shouldNegate())
530b57cec5SDimitry Andric OS << "!";
540b57cec5SDimitry Andric if (!FunctionMapper.empty())
550b57cec5SDimitry Andric OS << FunctionMapper << "(";
560b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
570b57cec5SDimitry Andric << ").getImm()";
580b57cec5SDimitry Andric if (!FunctionMapper.empty())
590b57cec5SDimitry Andric OS << ")";
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric
expandCheckImmOperandLT(raw_ostream & OS,int OpIndex,int ImmVal,StringRef FunctionMapper)62*b9d9368bSDimitry Andric void PredicateExpander::expandCheckImmOperandLT(raw_ostream &OS, int OpIndex,
63*b9d9368bSDimitry Andric int ImmVal,
64*b9d9368bSDimitry Andric StringRef FunctionMapper) {
65*b9d9368bSDimitry Andric if (!FunctionMapper.empty())
66*b9d9368bSDimitry Andric OS << FunctionMapper << "(";
67*b9d9368bSDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
68*b9d9368bSDimitry Andric << ").getImm()";
69*b9d9368bSDimitry Andric if (!FunctionMapper.empty())
70*b9d9368bSDimitry Andric OS << ")";
71*b9d9368bSDimitry Andric OS << (shouldNegate() ? " >= " : " < ") << ImmVal;
72*b9d9368bSDimitry Andric }
73*b9d9368bSDimitry Andric
expandCheckImmOperandGT(raw_ostream & OS,int OpIndex,int ImmVal,StringRef FunctionMapper)74*b9d9368bSDimitry Andric void PredicateExpander::expandCheckImmOperandGT(raw_ostream &OS, int OpIndex,
75*b9d9368bSDimitry Andric int ImmVal,
76*b9d9368bSDimitry Andric StringRef FunctionMapper) {
77*b9d9368bSDimitry Andric if (!FunctionMapper.empty())
78*b9d9368bSDimitry Andric OS << FunctionMapper << "(";
79*b9d9368bSDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
80*b9d9368bSDimitry Andric << ").getImm()";
81*b9d9368bSDimitry Andric if (!FunctionMapper.empty())
82*b9d9368bSDimitry Andric OS << ")";
83*b9d9368bSDimitry Andric OS << (shouldNegate() ? " <= " : " > ") << ImmVal;
84*b9d9368bSDimitry Andric }
85*b9d9368bSDimitry Andric
expandCheckRegOperand(raw_ostream & OS,int OpIndex,const Record * Reg,StringRef FunctionMapper)860b57cec5SDimitry Andric void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
870b57cec5SDimitry Andric const Record *Reg,
880b57cec5SDimitry Andric StringRef FunctionMapper) {
890b57cec5SDimitry Andric assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric if (!FunctionMapper.empty())
920b57cec5SDimitry Andric OS << FunctionMapper << "(";
930b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
940b57cec5SDimitry Andric << ").getReg()";
950b57cec5SDimitry Andric if (!FunctionMapper.empty())
960b57cec5SDimitry Andric OS << ")";
970b57cec5SDimitry Andric OS << (shouldNegate() ? " != " : " == ");
980b57cec5SDimitry Andric const StringRef Str = Reg->getValueAsString("Namespace");
990b57cec5SDimitry Andric if (!Str.empty())
1000b57cec5SDimitry Andric OS << Str << "::";
1010b57cec5SDimitry Andric OS << Reg->getName();
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric
1040b57cec5SDimitry Andric
expandCheckRegOperandSimple(raw_ostream & OS,int OpIndex,StringRef FunctionMapper)1050b57cec5SDimitry Andric void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
1060b57cec5SDimitry Andric int OpIndex,
1070b57cec5SDimitry Andric StringRef FunctionMapper) {
1080b57cec5SDimitry Andric if (shouldNegate())
1090b57cec5SDimitry Andric OS << "!";
1100b57cec5SDimitry Andric if (!FunctionMapper.empty())
1110b57cec5SDimitry Andric OS << FunctionMapper << "(";
1120b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
1130b57cec5SDimitry Andric << ").getReg()";
1140b57cec5SDimitry Andric if (!FunctionMapper.empty())
1150b57cec5SDimitry Andric OS << ")";
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric
expandCheckInvalidRegOperand(raw_ostream & OS,int OpIndex)1180b57cec5SDimitry Andric void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
1190b57cec5SDimitry Andric int OpIndex) {
1200b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
1210b57cec5SDimitry Andric << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric
expandCheckSameRegOperand(raw_ostream & OS,int First,int Second)1240b57cec5SDimitry Andric void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,
1250b57cec5SDimitry Andric int Second) {
1260b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
1270b57cec5SDimitry Andric << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
1280b57cec5SDimitry Andric << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric
expandCheckNumOperands(raw_ostream & OS,int NumOps)1310b57cec5SDimitry Andric void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
1320b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
1330b57cec5SDimitry Andric << (shouldNegate() ? "!= " : "== ") << NumOps;
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric
expandCheckOpcode(raw_ostream & OS,const Record * Inst)1360b57cec5SDimitry Andric void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
1370b57cec5SDimitry Andric OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
1380b57cec5SDimitry Andric << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
1390b57cec5SDimitry Andric << "::" << Inst->getName();
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric
expandCheckOpcode(raw_ostream & OS,const RecVec & Opcodes)1420b57cec5SDimitry Andric void PredicateExpander::expandCheckOpcode(raw_ostream &OS,
1430b57cec5SDimitry Andric const RecVec &Opcodes) {
1440b57cec5SDimitry Andric assert(!Opcodes.empty() && "Expected at least one opcode to check!");
1450b57cec5SDimitry Andric bool First = true;
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andric if (Opcodes.size() == 1) {
1480b57cec5SDimitry Andric OS << "( ";
1490b57cec5SDimitry Andric expandCheckOpcode(OS, Opcodes[0]);
1500b57cec5SDimitry Andric OS << " )";
1510b57cec5SDimitry Andric return;
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric
1540b57cec5SDimitry Andric OS << '(';
1550b57cec5SDimitry Andric increaseIndentLevel();
1560b57cec5SDimitry Andric for (const Record *Rec : Opcodes) {
1570b57cec5SDimitry Andric OS << '\n';
1580b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
1590b57cec5SDimitry Andric if (!First)
1600b57cec5SDimitry Andric OS << (shouldNegate() ? "&& " : "|| ");
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andric expandCheckOpcode(OS, Rec);
1630b57cec5SDimitry Andric First = false;
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric
1660b57cec5SDimitry Andric OS << '\n';
1670b57cec5SDimitry Andric decreaseIndentLevel();
1680b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
1690b57cec5SDimitry Andric OS << ')';
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric
expandCheckPseudo(raw_ostream & OS,const RecVec & Opcodes)1720b57cec5SDimitry Andric void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
1730b57cec5SDimitry Andric const RecVec &Opcodes) {
1740b57cec5SDimitry Andric if (shouldExpandForMC())
1750b57cec5SDimitry Andric expandFalse(OS);
1760b57cec5SDimitry Andric else
1770b57cec5SDimitry Andric expandCheckOpcode(OS, Opcodes);
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric
expandPredicateSequence(raw_ostream & OS,const RecVec & Sequence,bool IsCheckAll)1800b57cec5SDimitry Andric void PredicateExpander::expandPredicateSequence(raw_ostream &OS,
1810b57cec5SDimitry Andric const RecVec &Sequence,
1820b57cec5SDimitry Andric bool IsCheckAll) {
1830b57cec5SDimitry Andric assert(!Sequence.empty() && "Found an invalid empty predicate set!");
1840b57cec5SDimitry Andric if (Sequence.size() == 1)
1850b57cec5SDimitry Andric return expandPredicate(OS, Sequence[0]);
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andric // Okay, there is more than one predicate in the set.
1880b57cec5SDimitry Andric bool First = true;
1890b57cec5SDimitry Andric OS << (shouldNegate() ? "!(" : "(");
1900b57cec5SDimitry Andric increaseIndentLevel();
1910b57cec5SDimitry Andric
1920b57cec5SDimitry Andric bool OldValue = shouldNegate();
1930b57cec5SDimitry Andric setNegatePredicate(false);
1940b57cec5SDimitry Andric for (const Record *Rec : Sequence) {
1950b57cec5SDimitry Andric OS << '\n';
1960b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
1970b57cec5SDimitry Andric if (!First)
1980b57cec5SDimitry Andric OS << (IsCheckAll ? "&& " : "|| ");
1990b57cec5SDimitry Andric expandPredicate(OS, Rec);
2000b57cec5SDimitry Andric First = false;
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric OS << '\n';
2030b57cec5SDimitry Andric decreaseIndentLevel();
2040b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
2050b57cec5SDimitry Andric OS << ')';
2060b57cec5SDimitry Andric setNegatePredicate(OldValue);
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric
expandTIIFunctionCall(raw_ostream & OS,StringRef MethodName)2090b57cec5SDimitry Andric void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,
2100b57cec5SDimitry Andric StringRef MethodName) {
2110b57cec5SDimitry Andric OS << (shouldNegate() ? "!" : "");
2120b57cec5SDimitry Andric OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");
2130b57cec5SDimitry Andric OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric
expandCheckIsRegOperand(raw_ostream & OS,int OpIndex)2160b57cec5SDimitry Andric void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
2170b57cec5SDimitry Andric OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
2180b57cec5SDimitry Andric << "getOperand(" << OpIndex << ").isReg() ";
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric
expandCheckIsVRegOperand(raw_ostream & OS,int OpIndex)221cdc20ff6SDimitry Andric void PredicateExpander::expandCheckIsVRegOperand(raw_ostream &OS, int OpIndex) {
222cdc20ff6SDimitry Andric OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
223cdc20ff6SDimitry Andric << "getOperand(" << OpIndex << ").getReg().isVirtual()";
224cdc20ff6SDimitry Andric }
225cdc20ff6SDimitry Andric
expandCheckIsImmOperand(raw_ostream & OS,int OpIndex)2260b57cec5SDimitry Andric void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
2270b57cec5SDimitry Andric OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
2280b57cec5SDimitry Andric << "getOperand(" << OpIndex << ").isImm() ";
2290b57cec5SDimitry Andric }
2300b57cec5SDimitry Andric
expandCheckFunctionPredicateWithTII(raw_ostream & OS,StringRef MCInstFn,StringRef MachineInstrFn,StringRef TIIPtr)231e8d8bef9SDimitry Andric void PredicateExpander::expandCheckFunctionPredicateWithTII(
232e8d8bef9SDimitry Andric raw_ostream &OS, StringRef MCInstFn, StringRef MachineInstrFn,
233e8d8bef9SDimitry Andric StringRef TIIPtr) {
234e8d8bef9SDimitry Andric if (!shouldExpandForMC()) {
235e8d8bef9SDimitry Andric OS << (TIIPtr.empty() ? "TII" : TIIPtr) << "->" << MachineInstrFn;
236e8d8bef9SDimitry Andric OS << (isByRef() ? "(MI)" : "(*MI)");
237e8d8bef9SDimitry Andric return;
238e8d8bef9SDimitry Andric }
239e8d8bef9SDimitry Andric
240e8d8bef9SDimitry Andric OS << MCInstFn << (isByRef() ? "(MI" : "(*MI") << ", MCII)";
241e8d8bef9SDimitry Andric }
242e8d8bef9SDimitry Andric
expandCheckFunctionPredicate(raw_ostream & OS,StringRef MCInstFn,StringRef MachineInstrFn)2430b57cec5SDimitry Andric void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
2440b57cec5SDimitry Andric StringRef MCInstFn,
2450b57cec5SDimitry Andric StringRef MachineInstrFn) {
2460b57cec5SDimitry Andric OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
2470b57cec5SDimitry Andric << (isByRef() ? "(MI)" : "(*MI)");
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric
expandCheckNonPortable(raw_ostream & OS,StringRef Code)2500b57cec5SDimitry Andric void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
2510b57cec5SDimitry Andric StringRef Code) {
2520b57cec5SDimitry Andric if (shouldExpandForMC())
2530b57cec5SDimitry Andric return expandFalse(OS);
2540b57cec5SDimitry Andric
2550b57cec5SDimitry Andric OS << '(' << Code << ')';
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric
expandReturnStatement(raw_ostream & OS,const Record * Rec)2580b57cec5SDimitry Andric void PredicateExpander::expandReturnStatement(raw_ostream &OS,
2590b57cec5SDimitry Andric const Record *Rec) {
2600b57cec5SDimitry Andric std::string Buffer;
2610b57cec5SDimitry Andric raw_string_ostream SS(Buffer);
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andric SS << "return ";
2640b57cec5SDimitry Andric expandPredicate(SS, Rec);
2650b57cec5SDimitry Andric SS << ";";
2660b57cec5SDimitry Andric OS << Buffer;
2670b57cec5SDimitry Andric }
2680b57cec5SDimitry Andric
expandOpcodeSwitchCase(raw_ostream & OS,const Record * Rec)2690b57cec5SDimitry Andric void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
2700b57cec5SDimitry Andric const Record *Rec) {
2710b57cec5SDimitry Andric const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
2720b57cec5SDimitry Andric for (const Record *Opcode : Opcodes) {
2730b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
2740b57cec5SDimitry Andric OS << "case " << Opcode->getValueAsString("Namespace")
2750b57cec5SDimitry Andric << "::" << Opcode->getName() << ":\n";
2760b57cec5SDimitry Andric }
2770b57cec5SDimitry Andric
2780b57cec5SDimitry Andric increaseIndentLevel();
2790b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
2800b57cec5SDimitry Andric expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
2810b57cec5SDimitry Andric decreaseIndentLevel();
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric
expandOpcodeSwitchStatement(raw_ostream & OS,const RecVec & Cases,const Record * Default)2840b57cec5SDimitry Andric void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,
2850b57cec5SDimitry Andric const RecVec &Cases,
2860b57cec5SDimitry Andric const Record *Default) {
2870b57cec5SDimitry Andric std::string Buffer;
2880b57cec5SDimitry Andric raw_string_ostream SS(Buffer);
2890b57cec5SDimitry Andric
2900b57cec5SDimitry Andric SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
2910b57cec5SDimitry Andric for (const Record *Rec : Cases) {
2920b57cec5SDimitry Andric expandOpcodeSwitchCase(SS, Rec);
2930b57cec5SDimitry Andric SS << '\n';
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric
2960b57cec5SDimitry Andric // Expand the default case.
2970b57cec5SDimitry Andric SS.indent(getIndentLevel() * 2);
2980b57cec5SDimitry Andric SS << "default:\n";
2990b57cec5SDimitry Andric
3000b57cec5SDimitry Andric increaseIndentLevel();
3010b57cec5SDimitry Andric SS.indent(getIndentLevel() * 2);
3020b57cec5SDimitry Andric expandStatement(SS, Default);
3030b57cec5SDimitry Andric decreaseIndentLevel();
3040b57cec5SDimitry Andric SS << '\n';
3050b57cec5SDimitry Andric
3060b57cec5SDimitry Andric SS.indent(getIndentLevel() * 2);
3070b57cec5SDimitry Andric SS << "} // end of switch-stmt";
3080b57cec5SDimitry Andric OS << Buffer;
3090b57cec5SDimitry Andric }
3100b57cec5SDimitry Andric
expandStatement(raw_ostream & OS,const Record * Rec)3110b57cec5SDimitry Andric void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
3120b57cec5SDimitry Andric // Assume that padding has been added by the caller.
3130b57cec5SDimitry Andric if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
3140b57cec5SDimitry Andric expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
3150b57cec5SDimitry Andric Rec->getValueAsDef("DefaultCase"));
3160b57cec5SDimitry Andric return;
3170b57cec5SDimitry Andric }
3180b57cec5SDimitry Andric
3190b57cec5SDimitry Andric if (Rec->isSubClassOf("MCReturnStatement")) {
3200b57cec5SDimitry Andric expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
3210b57cec5SDimitry Andric return;
3220b57cec5SDimitry Andric }
3230b57cec5SDimitry Andric
3240b57cec5SDimitry Andric llvm_unreachable("No known rules to expand this MCStatement");
3250b57cec5SDimitry Andric }
3260b57cec5SDimitry Andric
expandPredicate(raw_ostream & OS,const Record * Rec)3270b57cec5SDimitry Andric void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
3280b57cec5SDimitry Andric // Assume that padding has been added by the caller.
3290b57cec5SDimitry Andric if (Rec->isSubClassOf("MCTrue")) {
3300b57cec5SDimitry Andric if (shouldNegate())
3310b57cec5SDimitry Andric return expandFalse(OS);
3320b57cec5SDimitry Andric return expandTrue(OS);
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric
3350b57cec5SDimitry Andric if (Rec->isSubClassOf("MCFalse")) {
3360b57cec5SDimitry Andric if (shouldNegate())
3370b57cec5SDimitry Andric return expandTrue(OS);
3380b57cec5SDimitry Andric return expandFalse(OS);
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric
3410b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckNot")) {
3420b57cec5SDimitry Andric flipNegatePredicate();
3430b57cec5SDimitry Andric expandPredicate(OS, Rec->getValueAsDef("Pred"));
3440b57cec5SDimitry Andric flipNegatePredicate();
3450b57cec5SDimitry Andric return;
3460b57cec5SDimitry Andric }
3470b57cec5SDimitry Andric
3480b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckIsRegOperand"))
3490b57cec5SDimitry Andric return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
3500b57cec5SDimitry Andric
351cdc20ff6SDimitry Andric if (Rec->isSubClassOf("CheckIsVRegOperand"))
352cdc20ff6SDimitry Andric return expandCheckIsVRegOperand(OS, Rec->getValueAsInt("OpIndex"));
353cdc20ff6SDimitry Andric
3540b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckIsImmOperand"))
3550b57cec5SDimitry Andric return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
3560b57cec5SDimitry Andric
3570b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckRegOperand"))
3580b57cec5SDimitry Andric return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
3590b57cec5SDimitry Andric Rec->getValueAsDef("Reg"),
3600b57cec5SDimitry Andric Rec->getValueAsString("FunctionMapper"));
3610b57cec5SDimitry Andric
3620b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckRegOperandSimple"))
3630b57cec5SDimitry Andric return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
3640b57cec5SDimitry Andric Rec->getValueAsString("FunctionMapper"));
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckInvalidRegOperand"))
3670b57cec5SDimitry Andric return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
3680b57cec5SDimitry Andric
3690b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckImmOperand"))
3700b57cec5SDimitry Andric return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
3710b57cec5SDimitry Andric Rec->getValueAsInt("ImmVal"),
3720b57cec5SDimitry Andric Rec->getValueAsString("FunctionMapper"));
3730b57cec5SDimitry Andric
3740b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckImmOperand_s"))
3750b57cec5SDimitry Andric return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
3760b57cec5SDimitry Andric Rec->getValueAsString("ImmVal"),
3770b57cec5SDimitry Andric Rec->getValueAsString("FunctionMapper"));
3780b57cec5SDimitry Andric
379*b9d9368bSDimitry Andric if (Rec->isSubClassOf("CheckImmOperandLT"))
380*b9d9368bSDimitry Andric return expandCheckImmOperandLT(OS, Rec->getValueAsInt("OpIndex"),
381*b9d9368bSDimitry Andric Rec->getValueAsInt("ImmVal"),
382*b9d9368bSDimitry Andric Rec->getValueAsString("FunctionMapper"));
383*b9d9368bSDimitry Andric
384*b9d9368bSDimitry Andric if (Rec->isSubClassOf("CheckImmOperandGT"))
385*b9d9368bSDimitry Andric return expandCheckImmOperandGT(OS, Rec->getValueAsInt("OpIndex"),
386*b9d9368bSDimitry Andric Rec->getValueAsInt("ImmVal"),
387*b9d9368bSDimitry Andric Rec->getValueAsString("FunctionMapper"));
388*b9d9368bSDimitry Andric
3890b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckImmOperandSimple"))
3900b57cec5SDimitry Andric return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
3910b57cec5SDimitry Andric Rec->getValueAsString("FunctionMapper"));
3920b57cec5SDimitry Andric
3930b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckSameRegOperand"))
3940b57cec5SDimitry Andric return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
3950b57cec5SDimitry Andric Rec->getValueAsInt("SecondIndex"));
3960b57cec5SDimitry Andric
3970b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckNumOperands"))
3980b57cec5SDimitry Andric return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
3990b57cec5SDimitry Andric
4000b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckPseudo"))
4010b57cec5SDimitry Andric return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckOpcode"))
4040b57cec5SDimitry Andric return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
4050b57cec5SDimitry Andric
4060b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckAll"))
4070b57cec5SDimitry Andric return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
4080b57cec5SDimitry Andric /* AllOf */ true);
4090b57cec5SDimitry Andric
4100b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckAny"))
4110b57cec5SDimitry Andric return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
4120b57cec5SDimitry Andric /* AllOf */ false);
4130b57cec5SDimitry Andric
414e8d8bef9SDimitry Andric if (Rec->isSubClassOf("CheckFunctionPredicate")) {
4150b57cec5SDimitry Andric return expandCheckFunctionPredicate(
4160b57cec5SDimitry Andric OS, Rec->getValueAsString("MCInstFnName"),
4170b57cec5SDimitry Andric Rec->getValueAsString("MachineInstrFnName"));
418e8d8bef9SDimitry Andric }
419e8d8bef9SDimitry Andric
420e8d8bef9SDimitry Andric if (Rec->isSubClassOf("CheckFunctionPredicateWithTII")) {
421e8d8bef9SDimitry Andric return expandCheckFunctionPredicateWithTII(
422e8d8bef9SDimitry Andric OS, Rec->getValueAsString("MCInstFnName"),
423e8d8bef9SDimitry Andric Rec->getValueAsString("MachineInstrFnName"),
424e8d8bef9SDimitry Andric Rec->getValueAsString("TIIPtrName"));
425e8d8bef9SDimitry Andric }
4260b57cec5SDimitry Andric
4270b57cec5SDimitry Andric if (Rec->isSubClassOf("CheckNonPortable"))
4280b57cec5SDimitry Andric return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
4290b57cec5SDimitry Andric
4300b57cec5SDimitry Andric if (Rec->isSubClassOf("TIIPredicate"))
4310b57cec5SDimitry Andric return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
4320b57cec5SDimitry Andric
4330b57cec5SDimitry Andric llvm_unreachable("No known rules to expand this MCInstPredicate");
4340b57cec5SDimitry Andric }
4350b57cec5SDimitry Andric
expandHeader(raw_ostream & OS,const STIPredicateFunction & Fn)4360b57cec5SDimitry Andric void STIPredicateExpander::expandHeader(raw_ostream &OS,
4370b57cec5SDimitry Andric const STIPredicateFunction &Fn) {
4380b57cec5SDimitry Andric const Record *Rec = Fn.getDeclaration();
4390b57cec5SDimitry Andric StringRef FunctionName = Rec->getValueAsString("Name");
4400b57cec5SDimitry Andric
4410b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
4420b57cec5SDimitry Andric OS << "bool ";
4430b57cec5SDimitry Andric if (shouldExpandDefinition())
4440b57cec5SDimitry Andric OS << getClassPrefix() << "::";
4450b57cec5SDimitry Andric OS << FunctionName << "(";
4460b57cec5SDimitry Andric if (shouldExpandForMC())
4470b57cec5SDimitry Andric OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";
4480b57cec5SDimitry Andric else
4490b57cec5SDimitry Andric OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
4500b57cec5SDimitry Andric if (Rec->getValueAsBit("UpdatesOpcodeMask"))
4510b57cec5SDimitry Andric OS << ", APInt &Mask";
4520b57cec5SDimitry Andric OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
4530b57cec5SDimitry Andric if (shouldExpandDefinition()) {
4540b57cec5SDimitry Andric OS << "{\n";
4550b57cec5SDimitry Andric return;
4560b57cec5SDimitry Andric }
4570b57cec5SDimitry Andric
4580b57cec5SDimitry Andric if (Rec->getValueAsBit("OverridesBaseClassMember"))
4590b57cec5SDimitry Andric OS << "override";
4600b57cec5SDimitry Andric OS << ";\n";
4610b57cec5SDimitry Andric }
4620b57cec5SDimitry Andric
expandPrologue(raw_ostream & OS,const STIPredicateFunction & Fn)4630b57cec5SDimitry Andric void STIPredicateExpander::expandPrologue(raw_ostream &OS,
4640b57cec5SDimitry Andric const STIPredicateFunction &Fn) {
4650b57cec5SDimitry Andric RecVec Delegates = Fn.getDeclaration()->getValueAsListOfDefs("Delegates");
4660b57cec5SDimitry Andric bool UpdatesOpcodeMask =
4670b57cec5SDimitry Andric Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
4680b57cec5SDimitry Andric
4690b57cec5SDimitry Andric increaseIndentLevel();
4700b57cec5SDimitry Andric unsigned IndentLevel = getIndentLevel();
4710b57cec5SDimitry Andric for (const Record *Delegate : Delegates) {
4720b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
4730b57cec5SDimitry Andric OS << "if (" << Delegate->getValueAsString("Name") << "(MI";
4740b57cec5SDimitry Andric if (UpdatesOpcodeMask)
4750b57cec5SDimitry Andric OS << ", Mask";
4760b57cec5SDimitry Andric if (shouldExpandForMC())
4770b57cec5SDimitry Andric OS << ", ProcessorID";
4780b57cec5SDimitry Andric OS << "))\n";
4790b57cec5SDimitry Andric OS.indent((1 + IndentLevel) * 2);
4800b57cec5SDimitry Andric OS << "return true;\n\n";
4810b57cec5SDimitry Andric }
4820b57cec5SDimitry Andric
4830b57cec5SDimitry Andric if (shouldExpandForMC())
4840b57cec5SDimitry Andric return;
4850b57cec5SDimitry Andric
4860b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
4870b57cec5SDimitry Andric OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric
expandOpcodeGroup(raw_ostream & OS,const OpcodeGroup & Group,bool ShouldUpdateOpcodeMask)4900b57cec5SDimitry Andric void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS, const OpcodeGroup &Group,
4910b57cec5SDimitry Andric bool ShouldUpdateOpcodeMask) {
4920b57cec5SDimitry Andric const OpcodeInfo &OI = Group.getOpcodeInfo();
4930b57cec5SDimitry Andric for (const PredicateInfo &PI : OI.getPredicates()) {
4940b57cec5SDimitry Andric const APInt &ProcModelMask = PI.ProcModelMask;
4950b57cec5SDimitry Andric bool FirstProcID = true;
4960b57cec5SDimitry Andric for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {
4970b57cec5SDimitry Andric if (!ProcModelMask[I])
4980b57cec5SDimitry Andric continue;
4990b57cec5SDimitry Andric
5000b57cec5SDimitry Andric if (FirstProcID) {
5010b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
5020b57cec5SDimitry Andric OS << "if (ProcessorID == " << I;
5030b57cec5SDimitry Andric } else {
5040b57cec5SDimitry Andric OS << " || ProcessorID == " << I;
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric FirstProcID = false;
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric
5090b57cec5SDimitry Andric OS << ") {\n";
5100b57cec5SDimitry Andric
5110b57cec5SDimitry Andric increaseIndentLevel();
5120b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
5130b57cec5SDimitry Andric if (ShouldUpdateOpcodeMask) {
514349cc55cSDimitry Andric if (PI.OperandMask.isZero())
5150b57cec5SDimitry Andric OS << "Mask.clearAllBits();\n";
5160b57cec5SDimitry Andric else
5170b57cec5SDimitry Andric OS << "Mask = " << PI.OperandMask << ";\n";
5180b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
5190b57cec5SDimitry Andric }
5200b57cec5SDimitry Andric OS << "return ";
5210b57cec5SDimitry Andric expandPredicate(OS, PI.Predicate);
5220b57cec5SDimitry Andric OS << ";\n";
5230b57cec5SDimitry Andric decreaseIndentLevel();
5240b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
5250b57cec5SDimitry Andric OS << "}\n";
5260b57cec5SDimitry Andric }
5270b57cec5SDimitry Andric }
5280b57cec5SDimitry Andric
expandBody(raw_ostream & OS,const STIPredicateFunction & Fn)5290b57cec5SDimitry Andric void STIPredicateExpander::expandBody(raw_ostream &OS,
5300b57cec5SDimitry Andric const STIPredicateFunction &Fn) {
5310b57cec5SDimitry Andric bool UpdatesOpcodeMask =
5320b57cec5SDimitry Andric Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
5330b57cec5SDimitry Andric
5340b57cec5SDimitry Andric unsigned IndentLevel = getIndentLevel();
5350b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
5360b57cec5SDimitry Andric OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
5370b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
5380b57cec5SDimitry Andric OS << "default:\n";
5390b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
5400b57cec5SDimitry Andric OS << " break;";
5410b57cec5SDimitry Andric
5420b57cec5SDimitry Andric for (const OpcodeGroup &Group : Fn.getGroups()) {
5430b57cec5SDimitry Andric for (const Record *Opcode : Group.getOpcodes()) {
5440b57cec5SDimitry Andric OS << '\n';
5450b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
5460b57cec5SDimitry Andric OS << "case " << getTargetName() << "::" << Opcode->getName() << ":";
5470b57cec5SDimitry Andric }
5480b57cec5SDimitry Andric
5490b57cec5SDimitry Andric OS << '\n';
5500b57cec5SDimitry Andric increaseIndentLevel();
5510b57cec5SDimitry Andric expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);
5520b57cec5SDimitry Andric
5530b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
5540b57cec5SDimitry Andric OS << "break;\n";
5550b57cec5SDimitry Andric decreaseIndentLevel();
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric
5580b57cec5SDimitry Andric OS.indent(IndentLevel * 2);
5590b57cec5SDimitry Andric OS << "}\n";
5600b57cec5SDimitry Andric }
5610b57cec5SDimitry Andric
expandEpilogue(raw_ostream & OS,const STIPredicateFunction & Fn)5620b57cec5SDimitry Andric void STIPredicateExpander::expandEpilogue(raw_ostream &OS,
5630b57cec5SDimitry Andric const STIPredicateFunction &Fn) {
5640b57cec5SDimitry Andric OS << '\n';
5650b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
5660b57cec5SDimitry Andric OS << "return ";
5670b57cec5SDimitry Andric expandPredicate(OS, Fn.getDefaultReturnPredicate());
5680b57cec5SDimitry Andric OS << ";\n";
5690b57cec5SDimitry Andric
5700b57cec5SDimitry Andric decreaseIndentLevel();
5710b57cec5SDimitry Andric OS.indent(getIndentLevel() * 2);
5720b57cec5SDimitry Andric StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");
5730b57cec5SDimitry Andric OS << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
5740b57cec5SDimitry Andric }
5750b57cec5SDimitry Andric
expandSTIPredicate(raw_ostream & OS,const STIPredicateFunction & Fn)5760b57cec5SDimitry Andric void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
5770b57cec5SDimitry Andric const STIPredicateFunction &Fn) {
5780b57cec5SDimitry Andric const Record *Rec = Fn.getDeclaration();
5790b57cec5SDimitry Andric if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))
5800b57cec5SDimitry Andric return;
5810b57cec5SDimitry Andric
5820b57cec5SDimitry Andric expandHeader(OS, Fn);
5830b57cec5SDimitry Andric if (shouldExpandDefinition()) {
5840b57cec5SDimitry Andric expandPrologue(OS, Fn);
5850b57cec5SDimitry Andric expandBody(OS, Fn);
5860b57cec5SDimitry Andric expandEpilogue(OS, Fn);
5870b57cec5SDimitry Andric }
5880b57cec5SDimitry Andric }
5890b57cec5SDimitry Andric
5900b57cec5SDimitry Andric } // namespace llvm
591