[RFC][Patch 1/3] Add a new class of predicates for variant scheduling classes.
This patch is the first of a sequence of three patches described by the LLVM-dev
RFC "MC support for variant scheduling classes".
http://lists.llvm.org/pipermail/llvm-dev/2018-May/123181.html
The goal of this patch is to introduce a new class of scheduling predicates for
SchedReadVariant and SchedWriteVariant.
An MCSchedPredicate can be used instead of a normal SchedPredicate to model
checks on the instruction (either a MachineInstr or a MCInst).
Internally, an MCSchedPredicate encapsulates an MCInstPredicate definition.
MCInstPredicate allows the definition of expressions with a well-known semantic,
that can be used to generate code for both MachineInstr and MCInst.
This is the first step toward teaching to tools like lllvm-mca how to resolve
variant scheduling classes.
Differential Revision: https://reviews.llvm.org/D46695
llvm-svn: 333282
diff --git a/llvm/utils/TableGen/CMakeLists.txt b/llvm/utils/TableGen/CMakeLists.txt
index bd7eca4..0428249 100644
--- a/llvm/utils/TableGen/CMakeLists.txt
+++ b/llvm/utils/TableGen/CMakeLists.txt
@@ -29,6 +29,7 @@
InstrDocsEmitter.cpp
IntrinsicEmitter.cpp
OptParserEmitter.cpp
+ PredicateExpander.cpp
PseudoLoweringEmitter.cpp
RISCVCompressInstEmitter.cpp
RegisterBankEmitter.cpp
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
index 85666af..61c3f1d 100644
--- a/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -16,6 +16,7 @@
#include "CodeGenInstruction.h"
#include "CodeGenSchedule.h"
#include "CodeGenTarget.h"
+#include "PredicateExpander.h"
#include "SequenceToOffsetTable.h"
#include "TableGenBackends.h"
#include "llvm/ADT/ArrayRef.h"
@@ -59,6 +60,13 @@
typedef std::map<std::map<unsigned, unsigned>,
std::vector<std::string>> OpNameMapTy;
typedef std::map<std::string, unsigned>::iterator StrUintMapIter;
+
+ /// Generate member functions in the target-specific GenInstrInfo class.
+ ///
+ /// This method is used to custom expand TIIPredicate definitions.
+ /// See file llvm/Target/TargetInstPredicates.td for a description of what is
+ /// a TIIPredicate and how to use it.
+ void emitTIIHelperMethods(raw_ostream &OS);
void emitRecord(const CodeGenInstruction &Inst, unsigned Num,
Record *InstrInfo,
std::map<std::vector<Record*>, unsigned> &EL,
@@ -339,6 +347,25 @@
OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n\n";
}
+void InstrInfoEmitter::emitTIIHelperMethods(raw_ostream &OS) {
+ RecVec TIIPredicates = Records.getAllDerivedDefinitions("TIIPredicate");
+ if (TIIPredicates.empty())
+ return;
+
+ formatted_raw_ostream FOS(OS);
+ PredicateExpander PE;
+ PE.setExpandForMC(false);
+ PE.setIndentLevel(2);
+
+ for (const Record *Rec : TIIPredicates) {
+ FOS << "\n static bool " << Rec->getValueAsString("FunctionName");
+ FOS << "(const MachineInstr &MI) {\n";
+ FOS << " return ";
+ PE.expandPredicate(FOS, Rec->getValueAsDef("Pred"));
+ FOS << ";\n }\n";
+ }
+}
+
//===----------------------------------------------------------------------===//
// Main Output.
//===----------------------------------------------------------------------===//
@@ -435,9 +462,11 @@
OS << "struct " << ClassName << " : public TargetInstrInfo {\n"
<< " explicit " << ClassName
<< "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1, int CatchRetOpcode = -1, int ReturnOpcode = -1);\n"
- << " ~" << ClassName << "() override = default;\n"
- << "};\n";
- OS << "} // end llvm namespace\n";
+ << " ~" << ClassName << "() override = default;\n";
+
+ emitTIIHelperMethods(OS);
+
+ OS << "\n};\n} // end llvm namespace\n";
OS << "#endif // GET_INSTRINFO_HEADER\n\n";
diff --git a/llvm/utils/TableGen/PredicateExpander.cpp b/llvm/utils/TableGen/PredicateExpander.cpp
new file mode 100644
index 0000000..62a01dc
--- /dev/null
+++ b/llvm/utils/TableGen/PredicateExpander.cpp
@@ -0,0 +1,253 @@
+//===--------------------- PredicateExpander.cpp --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// Functionalities used by the Tablegen backends to expand machine predicates.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PredicateExpander.h"
+
+namespace llvm {
+
+void PredicateExpander::expandTrue(formatted_raw_ostream &OS) { OS << "true"; }
+void PredicateExpander::expandFalse(formatted_raw_ostream &OS) {
+ OS << "false";
+}
+
+void PredicateExpander::expandCheckImmOperand(formatted_raw_ostream &OS,
+ int OpIndex, int ImmVal) {
+ OS << "MI.getOperand(" << OpIndex << ").getImm() "
+ << (shouldNegate() ? "!= " : "== ") << ImmVal;
+}
+
+void PredicateExpander::expandCheckImmOperand(formatted_raw_ostream &OS,
+ int OpIndex, StringRef ImmVal) {
+ OS << "MI.getOperand(" << OpIndex << ").getImm() "
+ << (shouldNegate() ? "!= " : "== ") << ImmVal;
+}
+
+void PredicateExpander::expandCheckRegOperand(formatted_raw_ostream &OS,
+ int OpIndex, const Record *Reg) {
+ assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
+
+ OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
+ << ").getReg() " << (shouldNegate() ? "!= " : "== ");
+ const StringRef Str = Reg->getValueAsString("Namespace");
+ if (!Str.empty())
+ OS << Str << "::";
+ OS << Reg->getName();
+}
+
+void PredicateExpander::expandCheckSameRegOperand(formatted_raw_ostream &OS,
+ int First, int Second) {
+ OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
+ << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
+ << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
+}
+
+void PredicateExpander::expandCheckNumOperands(formatted_raw_ostream &OS,
+ int NumOps) {
+ OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
+ << (shouldNegate() ? "!= " : "== ") << NumOps;
+}
+
+void PredicateExpander::expandCheckOpcode(formatted_raw_ostream &OS,
+ const Record *Inst) {
+ OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
+ << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
+ << "::" << Inst->getName();
+}
+
+void PredicateExpander::expandCheckOpcode(formatted_raw_ostream &OS,
+ const RecVec &Opcodes) {
+ assert(!Opcodes.empty() && "Expected at least one opcode to check!");
+ bool First = true;
+
+ if (Opcodes.size() == 1) {
+ OS << "( ";
+ expandCheckOpcode(OS, Opcodes[0]);
+ OS << " )";
+ return;
+ }
+
+ OS << '(';
+ increaseIndentLevel();
+ for (const Record *Rec : Opcodes) {
+ OS << '\n';
+ OS.PadToColumn(getIndentLevel() * 2);
+ if (!First)
+ OS << (shouldNegate() ? "&& " : "|| ");
+
+ expandCheckOpcode(OS, Rec);
+ First = false;
+ }
+
+ OS << '\n';
+ decreaseIndentLevel();
+ OS.PadToColumn(getIndentLevel() * 2);
+ OS << ')';
+}
+
+void PredicateExpander::expandCheckPseudo(formatted_raw_ostream &OS,
+ const RecVec &Opcodes) {
+ if (shouldExpandForMC())
+ expandFalse(OS);
+ else
+ expandCheckOpcode(OS, Opcodes);
+}
+
+void PredicateExpander::expandPredicateSequence(formatted_raw_ostream &OS,
+ const RecVec &Sequence,
+ bool IsCheckAll) {
+ assert(!Sequence.empty() && "Found an invalid empty predicate set!");
+ if (Sequence.size() == 1)
+ return expandPredicate(OS, Sequence[0]);
+
+ // Okay, there is more than one predicate in the set.
+ bool First = true;
+ OS << (shouldNegate() ? "!(" : "(");
+ increaseIndentLevel();
+
+ bool OldValue = shouldNegate();
+ setNegatePredicate(false);
+ for (const Record *Rec : Sequence) {
+ OS << '\n';
+ OS.PadToColumn(getIndentLevel() * 2);
+ if (!First)
+ OS << (IsCheckAll ? "&& " : "|| ");
+ expandPredicate(OS, Rec);
+ First = false;
+ }
+ OS << '\n';
+ decreaseIndentLevel();
+ OS.PadToColumn(getIndentLevel() * 2);
+ OS << ')';
+ setNegatePredicate(OldValue);
+}
+
+void PredicateExpander::expandTIIFunctionCall(formatted_raw_ostream &OS,
+ StringRef TargetName,
+ StringRef MethodName) {
+ OS << (shouldNegate() ? "!" : "");
+ if (shouldExpandForMC())
+ OS << TargetName << "_MC::";
+ else
+ OS << TargetName << "Gen"
+ << "InstrInfo::";
+ OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
+}
+
+void PredicateExpander::expandCheckIsRegOperand(formatted_raw_ostream &OS,
+ int OpIndex) {
+ OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
+ << "getOperand(" << OpIndex << ").isReg() ";
+}
+
+void PredicateExpander::expandCheckIsImmOperand(formatted_raw_ostream &OS,
+ int OpIndex) {
+ OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
+ << "getOperand(" << OpIndex << ").isImm() ";
+}
+
+void PredicateExpander::expandCheckFunctionPredicate(formatted_raw_ostream &OS,
+ StringRef MCInstFn,
+ StringRef MachineInstrFn) {
+ OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
+ << (isByRef() ? "(MI)" : "(*MI)");
+}
+
+void PredicateExpander::expandCheckNonPortable(formatted_raw_ostream &OS,
+ StringRef Code) {
+ if (shouldExpandForMC())
+ return expandFalse(OS);
+
+ OS << '(' << Code << ')';
+}
+
+void PredicateExpander::expandPredicate(formatted_raw_ostream &OS,
+ const Record *Rec) {
+ OS.flush();
+ unsigned ColNum = getIndentLevel() * 2;
+ if (OS.getColumn() < ColNum)
+ OS.PadToColumn(ColNum);
+
+ if (Rec->isSubClassOf("MCTrue")) {
+ if (shouldNegate())
+ return expandFalse(OS);
+ return expandTrue(OS);
+ }
+
+ if (Rec->isSubClassOf("MCFalse")) {
+ if (shouldNegate())
+ return expandTrue(OS);
+ return expandFalse(OS);
+ }
+
+ if (Rec->isSubClassOf("CheckNot")) {
+ flipNegatePredicate();
+ expandPredicate(OS, Rec->getValueAsDef("Pred"));
+ flipNegatePredicate();
+ return;
+ }
+
+ if (Rec->isSubClassOf("CheckIsRegOperand"))
+ return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
+
+ if (Rec->isSubClassOf("CheckIsImmOperand"))
+ return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
+
+ if (Rec->isSubClassOf("CheckRegOperand"))
+ return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
+ Rec->getValueAsDef("Reg"));
+
+ if (Rec->isSubClassOf("CheckImmOperand"))
+ return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
+ Rec->getValueAsInt("ImmVal"));
+
+ if (Rec->isSubClassOf("CheckImmOperand_s"))
+ return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
+ Rec->getValueAsString("ImmVal"));
+
+ if (Rec->isSubClassOf("CheckSameRegOperand"))
+ return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
+ Rec->getValueAsInt("SecondIndex"));
+
+ if (Rec->isSubClassOf("CheckNumOperands"))
+ return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
+
+ if (Rec->isSubClassOf("CheckPseudo"))
+ return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
+
+ if (Rec->isSubClassOf("CheckOpcode"))
+ return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
+
+ if (Rec->isSubClassOf("CheckAll"))
+ return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
+ /* AllOf */ true);
+
+ if (Rec->isSubClassOf("CheckAny"))
+ return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
+ /* AllOf */ false);
+
+ if (Rec->isSubClassOf("CheckFunctionPredicate"))
+ return expandCheckFunctionPredicate(
+ OS, Rec->getValueAsString("MCInstFnName"),
+ Rec->getValueAsString("MachineInstrFnName"));
+
+ if (Rec->isSubClassOf("CheckNonPortable"))
+ return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
+
+ if (Rec->isSubClassOf("TIIPredicate"))
+ return expandTIIFunctionCall(OS, Rec->getValueAsString("TargetName"),
+ Rec->getValueAsString("FunctionName"));
+
+ llvm_unreachable("No known rules to expand this MCInstPredicate");
+}
+
+} // namespace llvm
diff --git a/llvm/utils/TableGen/PredicateExpander.h b/llvm/utils/TableGen/PredicateExpander.h
new file mode 100644
index 0000000..bc4de90
--- /dev/null
+++ b/llvm/utils/TableGen/PredicateExpander.h
@@ -0,0 +1,85 @@
+//===--------------------- PredicateExpander.h ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// Functionalities used by the Tablegen backends to expand machine predicates.
+///
+/// See file llvm/Target/TargetInstrPredicate.td for a full list and description
+/// of all the supported MCInstPredicate classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_PREDICATEEXPANDER_H
+#define LLVM_UTILS_TABLEGEN_PREDICATEEXPANDER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/TableGen/Record.h"
+
+namespace llvm {
+
+class formatted_raw_ostream;
+
+class PredicateExpander {
+ bool EmitCallsByRef;
+ bool NegatePredicate;
+ bool ExpandForMC;
+ unsigned IndentLevel;
+
+ PredicateExpander(const PredicateExpander &) = delete;
+ PredicateExpander &operator=(const PredicateExpander &) = delete;
+
+public:
+ PredicateExpander()
+ : EmitCallsByRef(true), NegatePredicate(false), ExpandForMC(false),
+ IndentLevel(1U) {}
+ bool isByRef() const { return EmitCallsByRef; }
+ bool shouldNegate() const { return NegatePredicate; }
+ bool shouldExpandForMC() const { return ExpandForMC; }
+ unsigned getIndentLevel() const { return IndentLevel; }
+
+ void setByRef(bool Value) { EmitCallsByRef = Value; }
+ void flipNegatePredicate() { NegatePredicate = !NegatePredicate; }
+ void setNegatePredicate(bool Value) { NegatePredicate = Value; }
+ void setExpandForMC(bool Value) { ExpandForMC = Value; }
+ void increaseIndentLevel() { ++IndentLevel; }
+ void decreaseIndentLevel() { --IndentLevel; }
+ void setIndentLevel(unsigned Level) { IndentLevel = Level; }
+
+ using RecVec = std::vector<Record *>;
+ void expandTrue(formatted_raw_ostream &OS);
+ void expandFalse(formatted_raw_ostream &OS);
+ void expandCheckImmOperand(formatted_raw_ostream &OS, int OpIndex,
+ int ImmVal);
+ void expandCheckImmOperand(formatted_raw_ostream &OS, int OpIndex,
+ StringRef ImmVal);
+ void expandCheckRegOperand(formatted_raw_ostream &OS, int OpIndex,
+ const Record *Reg);
+ void expandCheckSameRegOperand(formatted_raw_ostream &OS, int First,
+ int Second);
+ void expandCheckNumOperands(formatted_raw_ostream &OS, int NumOps);
+ void expandCheckOpcode(formatted_raw_ostream &OS, const Record *Inst);
+
+ void expandCheckPseudo(formatted_raw_ostream &OS, const RecVec &Opcodes);
+ void expandCheckOpcode(formatted_raw_ostream &OS, const RecVec &Opcodes);
+ void expandPredicateSequence(formatted_raw_ostream &OS,
+ const RecVec &Sequence, bool IsCheckAll);
+ void expandTIIFunctionCall(formatted_raw_ostream &OS, StringRef TargetName,
+ StringRef MethodName);
+ void expandCheckIsRegOperand(formatted_raw_ostream &OS, int OpIndex);
+ void expandCheckIsImmOperand(formatted_raw_ostream &OS, int OpIndex);
+ void expandCheckFunctionPredicate(formatted_raw_ostream &OS,
+ StringRef MCInstFn,
+ StringRef MachineInstrFn);
+ void expandCheckNonPortable(formatted_raw_ostream &OS, StringRef CodeBlock);
+ void expandPredicate(formatted_raw_ostream &OS, const Record *Rec);
+};
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp
index 5fd145f..d110f80 100644
--- a/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -13,6 +13,7 @@
#include "CodeGenTarget.h"
#include "CodeGenSchedule.h"
+#include "PredicateExpander.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
@@ -112,6 +113,9 @@
void EmitProcessorModels(raw_ostream &OS);
void EmitProcessorLookup(raw_ostream &OS);
void EmitSchedModelHelpers(const std::string &ClassName, raw_ostream &OS);
+ void emitSchedModelHelpersImpl(raw_ostream &OS,
+ bool OnlyExpandMCInstPredicates = false);
+
void EmitSchedModel(raw_ostream &OS);
void EmitHwModeCheck(const std::string &ClassName, raw_ostream &OS);
void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
@@ -1461,35 +1465,37 @@
}
static void emitPredicates(const CodeGenSchedTransition &T,
- const CodeGenSchedClass &SC, unsigned ProcIdx,
+ const CodeGenSchedClass &SC,
+ PredicateExpander &PE,
raw_ostream &OS) {
- if (ProcIdx && !count(T.ProcIndices, ProcIdx))
- return;
-
std::string Buffer;
- raw_string_ostream Stream(Buffer);
- Stream << " if (";
+ raw_string_ostream StringStream(Buffer);
+ formatted_raw_ostream FOS(StringStream);
+
+ FOS.PadToColumn(6);
+ FOS << "if (";
for (RecIter RI = T.PredTerm.begin(), RE = T.PredTerm.end(); RI != RE; ++RI) {
- if (RI != T.PredTerm.begin())
- Stream << "\n && ";
- Stream << "(" << (*RI)->getValueAsString("Predicate") << ")";
+ if (RI != T.PredTerm.begin()) {
+ FOS << "\n";
+ FOS.PadToColumn(8);
+ FOS << "&& ";
+ }
+ const Record *Rec = *RI;
+ if (Rec->isSubClassOf("MCSchedPredicate"))
+ PE.expandPredicate(FOS, Rec->getValueAsDef("Pred"));
+ else
+ FOS << "(" << Rec->getValueAsString("Predicate") << ")";
}
- Stream << ")\n"
- << " return " << T.ToClassIdx << "; // " << SC.Name << '\n';
- Stream.flush();
+ FOS << ")\n";
+ FOS.PadToColumn(8);
+ FOS << "return " << T.ToClassIdx << "; // " << SC.Name << '\n';
+ FOS.flush();
OS << Buffer;
}
-void SubtargetEmitter::EmitSchedModelHelpers(const std::string &ClassName,
- raw_ostream &OS) {
- OS << "unsigned " << ClassName
- << "\n::resolveSchedClass(unsigned SchedClass, const MachineInstr *MI,"
- << " const TargetSchedModel *SchedModel) const {\n";
-
- // Emit the predicate prolog code.
- emitPredicateProlog(Records, OS);
-
+void SubtargetEmitter::emitSchedModelHelpersImpl(
+ raw_ostream &OS, bool OnlyExpandMCInstPredicates) {
// Collect Variant Classes.
IdxVec VariantClasses;
for (const CodeGenSchedClass &SC : SchedModels.schedClasses()) {
@@ -1503,24 +1509,43 @@
for (unsigned VC : VariantClasses) {
// Emit code for each variant scheduling class.
const CodeGenSchedClass &SC = SchedModels.getSchedClass(VC);
- OS << " case " << VC << ": // " << SC.Name << '\n';
IdxVec ProcIndices;
for (const CodeGenSchedTransition &T : SC.Transitions) {
+ if (OnlyExpandMCInstPredicates &&
+ !all_of(T.PredTerm, [](const Record *Rec) {
+ return Rec->isSubClassOf("MCSchedPredicate");
+ }))
+ continue;
+
IdxVec PI;
std::set_union(T.ProcIndices.begin(), T.ProcIndices.end(),
ProcIndices.begin(), ProcIndices.end(),
std::back_inserter(PI));
ProcIndices.swap(PI);
}
+ if (ProcIndices.empty())
+ continue;
+
+ OS << " case " << VC << ": // " << SC.Name << '\n';
+ PredicateExpander PE;
+ PE.setByRef(false);
+ PE.setExpandForMC(OnlyExpandMCInstPredicates);
for (unsigned PI : ProcIndices) {
OS << " ";
- if (PI != 0)
- OS << "if (SchedModel->getProcessorID() == " << PI << ") ";
- OS << "{ // " << (SchedModels.procModelBegin() + PI)->ModelName
- << '\n';
+ if (PI != 0) {
+ OS << (OnlyExpandMCInstPredicates
+ ? "if (CPUID == "
+ : "if (SchedModel->getProcessorID() == ");
+ OS << PI << ") ";
+ }
+ OS << "{ // " << (SchedModels.procModelBegin() + PI)->ModelName << '\n';
- for (const CodeGenSchedTransition &T : SC.Transitions)
- emitPredicates(T, SchedModels.getSchedClass(T.ToClassIdx), PI, OS);
+ for (const CodeGenSchedTransition &T : SC.Transitions) {
+ if (PI != 0 && !count(T.ProcIndices, PI))
+ continue;
+ PE.setIndentLevel(4);
+ emitPredicates(T, SchedModels.getSchedClass(T.ToClassIdx), PE, OS);
+ }
OS << " }\n";
if (PI == 0)
@@ -1532,8 +1557,29 @@
}
OS << " };\n";
}
- OS << " report_fatal_error(\"Expected a variant SchedClass\");\n"
- << "} // " << ClassName << "::resolveSchedClass\n";
+
+ if (OnlyExpandMCInstPredicates) {
+ OS << " // Don't know how to resolve this scheduling class.\n"
+ << " return 0;\n";
+ return;
+ }
+
+ OS << " report_fatal_error(\"Expected a variant SchedClass\");\n";
+}
+
+void SubtargetEmitter::EmitSchedModelHelpers(const std::string &ClassName,
+ raw_ostream &OS) {
+ OS << "unsigned " << ClassName
+ << "\n::resolveSchedClass(unsigned SchedClass, const MachineInstr *MI,"
+ << " const TargetSchedModel *SchedModel) const {\n";
+
+ // Emit the predicate prolog code.
+ emitPredicateProlog(Records, OS);
+
+ // Emit target predicates.
+ emitSchedModelHelpersImpl(OS);
+
+ OS << "} // " << ClassName << "::resolveSchedClass\n";
}
void SubtargetEmitter::EmitHwModeCheck(const std::string &ClassName,