forked from OSchip/llvm-project
[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
This commit is contained in:
parent
c80c873837
commit
95140023b5
|
@ -383,6 +383,11 @@ class DwarfRegAlias<Register reg> {
|
||||||
Register DwarfAlias = reg;
|
Register DwarfAlias = reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Pull in the common support for MCPredicate (portable scheduling predicates).
|
||||||
|
//
|
||||||
|
include "llvm/Target/TargetInstrPredicate.td"
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Pull in the common support for scheduling
|
// Pull in the common support for scheduling
|
||||||
//
|
//
|
||||||
|
|
|
@ -0,0 +1,194 @@
|
||||||
|
//===- TargetInstrPredicate.td - ---------------------------*- tablegen -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file defines MCInstPredicate classes and its subclasses.
|
||||||
|
//
|
||||||
|
// MCInstPredicate is used to describe constraints on the opcode/operand(s) of
|
||||||
|
// an instruction. Each MCInstPredicate class has a well-known semantic, and it
|
||||||
|
// is used by a PredicateExpander to generate code for MachineInstr and/or
|
||||||
|
// MCInst.
|
||||||
|
//
|
||||||
|
// MCInstPredicate definitions can be used to construct MCSchedPredicate
|
||||||
|
// definitions. An MCSchedPredicate can be used in place of a SchedPredicate
|
||||||
|
// when defining SchedReadVariant and SchedWriteVariant used by a processor
|
||||||
|
// scheduling model.
|
||||||
|
//
|
||||||
|
// Here is an example of MCInstPredicate definition:
|
||||||
|
//
|
||||||
|
// def MCInstPredicateExample : CheckAll<[
|
||||||
|
// CheckOpcode<[BLR]>,
|
||||||
|
// CheckIsRegOperand<0>,
|
||||||
|
// CheckNot<CheckRegOperand<0, LR>>]>;
|
||||||
|
//
|
||||||
|
// Predicate `MCInstPredicateExample` checks that the machine instruction in
|
||||||
|
// input is a BLR, and that operand at index 0 is register `LR`.
|
||||||
|
//
|
||||||
|
// That predicate could be used to rewrite the following definition (from
|
||||||
|
// AArch64SchedExynosM3.td):
|
||||||
|
//
|
||||||
|
// def M3BranchLinkFastPred : SchedPredicate<[{
|
||||||
|
// MI->getOpcode() == AArch64::BLR &&
|
||||||
|
// MI->getOperand(0).isReg() &&
|
||||||
|
// MI->getOperand(0).getReg() != AArch64::LR}]>;
|
||||||
|
//
|
||||||
|
// MCInstPredicate definitions are used to construct MCSchedPredicate (see the
|
||||||
|
// definition of class MCSchedPredicate in llvm/Target/TargetSchedule.td). An
|
||||||
|
// MCSchedPredicate can be used by a `SchedVar` to associate a predicate with a
|
||||||
|
// list of SchedReadWrites. Note that `SchedVar` are used to create SchedVariant
|
||||||
|
// definitions.
|
||||||
|
//
|
||||||
|
// Each MCInstPredicate class has a well known semantic. For example,
|
||||||
|
// `CheckOpcode` is only used to check the instruction opcode value.
|
||||||
|
//
|
||||||
|
// MCInstPredicate classes allow the definition of predicates in a declarative
|
||||||
|
// way. These predicates don't require a custom block of C++, and can be used
|
||||||
|
// to define conditions on instructions without being bound to a particular
|
||||||
|
// representation (i.e. MachineInstr vs MCInst).
|
||||||
|
//
|
||||||
|
// It also means that tablegen backends must know how to parse and expand them
|
||||||
|
// into code that works on MCInst (or MachineInst).
|
||||||
|
//
|
||||||
|
// Instances of class PredicateExpander (see utils/Tablegen/PredicateExpander.h)
|
||||||
|
// know how to expand a predicate. For each MCInstPredicate class, there must be
|
||||||
|
// an "expand" method available in the PredicateExpander interface.
|
||||||
|
//
|
||||||
|
// For example, a `CheckOpcode` predicate is expanded using method
|
||||||
|
// `PredicateExpander::expandCheckOpcode()`.
|
||||||
|
//
|
||||||
|
// New MCInstPredicate classes must be added to this file. For each new class
|
||||||
|
// XYZ, an "expandXYZ" method must be added to the PredicateExpander.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Forward declarations.
|
||||||
|
class Instruction;
|
||||||
|
|
||||||
|
// A generic machine instruction predicate.
|
||||||
|
class MCInstPredicate;
|
||||||
|
|
||||||
|
class MCTrue : MCInstPredicate; // A predicate that always evaluates to True.
|
||||||
|
class MCFalse : MCInstPredicate; // A predicate that always evaluates to False.
|
||||||
|
def TruePred : MCTrue;
|
||||||
|
def FalsePred : MCFalse;
|
||||||
|
|
||||||
|
// A predicate used to negate the outcome of another predicate.
|
||||||
|
// It allows to easily express "set difference" operations. For example, it
|
||||||
|
// makes it easy to describe a check that tests if an opcode is not part of a
|
||||||
|
// set of opcodes.
|
||||||
|
class CheckNot<MCInstPredicate P> : MCInstPredicate {
|
||||||
|
MCInstPredicate Pred = P;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This class is used as a building block to define predicates on instruction
|
||||||
|
// operands. It is used to reference a specific machine operand.
|
||||||
|
class MCOperandPredicate<int Index> : MCInstPredicate {
|
||||||
|
int OpIndex = Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if machine operand at position `Index` is a register operand.
|
||||||
|
class CheckIsRegOperand<int Index> : MCOperandPredicate<Index>;
|
||||||
|
|
||||||
|
// Return true if machine operand at position `Index` is an immediate operand.
|
||||||
|
class CheckIsImmOperand<int Index> : MCOperandPredicate<Index>;
|
||||||
|
|
||||||
|
// Check if machine operands at index `First` and index `Second` both reference
|
||||||
|
// the same register.
|
||||||
|
class CheckSameRegOperand<int First, int Second> : MCInstPredicate {
|
||||||
|
int FirstIndex = First;
|
||||||
|
int SecondIndex = Second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the machine register operand at position `Index` references
|
||||||
|
// register R. This predicate assumes that we already checked that the machine
|
||||||
|
// operand at position `Index` is a register operand.
|
||||||
|
class CheckRegOperand<int Index, Register R> : MCOperandPredicate<Index> {
|
||||||
|
Register Reg = R;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the operand at position `Index` is immediate `Imm`.
|
||||||
|
class CheckImmOperand<int Index, int Imm> : MCOperandPredicate<Index> {
|
||||||
|
int ImmVal = Imm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Similar to CheckImmOperand, however the immediate is not a literal number.
|
||||||
|
// This is useful when we want to compare the value of an operand against an
|
||||||
|
// enum value, and we know the actual integer value of that enum.
|
||||||
|
class CheckImmOperand_s<int Index, string Value> : MCOperandPredicate<Index> {
|
||||||
|
string ImmVal = Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the operand at position `Index` is immediate value zero.
|
||||||
|
class CheckZeroOperand<int Index> : CheckImmOperand<Index, 0>;
|
||||||
|
|
||||||
|
// Check that the instruction has exactly `Num` operands.
|
||||||
|
class CheckNumOperands<int Num> : MCInstPredicate {
|
||||||
|
int NumOps = Num;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the instruction opcode is one of the opcodes in set `Opcodes`.
|
||||||
|
// This is a simple set membership query. The easier way to check if an opcode
|
||||||
|
// is not a member of the set is by using a `CheckNot<CheckOpcode<[...]>>`
|
||||||
|
// sequence.
|
||||||
|
class CheckOpcode<list<Instruction> Opcodes> : MCInstPredicate {
|
||||||
|
list<Instruction> ValidOpcodes = Opcodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the instruction opcode is a pseudo opcode member of the set
|
||||||
|
// `Opcodes`. This check is always expanded to "false" if we are generating
|
||||||
|
// code for MCInst.
|
||||||
|
class CheckPseudo<list<Instruction> Opcodes> : CheckOpcode<Opcodes>;
|
||||||
|
|
||||||
|
// A non-portable predicate. Only to use as a last resort when a block of code
|
||||||
|
// cannot possibly be converted in a declarative way using other MCInstPredicate
|
||||||
|
// classes. This check is always expanded to "false" when generating code for
|
||||||
|
// MCInst.
|
||||||
|
class CheckNonPortable<string Code> : MCInstPredicate {
|
||||||
|
string CodeBlock = Code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A sequence of predicates. It is used as the base class for CheckAll, and
|
||||||
|
// CheckAny. It allows to describe compositions of predicates.
|
||||||
|
class CheckPredicateSequence<list<MCInstPredicate> Preds> : MCInstPredicate {
|
||||||
|
list<MCInstPredicate> Predicates = Preds;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that all of the predicates in `Preds` evaluate to true.
|
||||||
|
class CheckAll<list<MCInstPredicate> Sequence>
|
||||||
|
: CheckPredicateSequence<Sequence>;
|
||||||
|
|
||||||
|
// Check that at least one of the predicates in `Preds` evaluates to true.
|
||||||
|
class CheckAny<list<MCInstPredicate> Sequence>
|
||||||
|
: CheckPredicateSequence<Sequence>;
|
||||||
|
|
||||||
|
// Check that a call to method `Name` in class "XXXGenInstrInfo" (where XXX is
|
||||||
|
// the `Target` name) returns true.
|
||||||
|
//
|
||||||
|
// TIIPredicate definitions are used to model calls to the target-specific
|
||||||
|
// InstrInfo. A TIIPredicate is treated specially by the InstrInfoEmitter
|
||||||
|
// tablegen backend, which will use it to automatically generate a definition in
|
||||||
|
// the target specific `GenInstrInfo` class.
|
||||||
|
class TIIPredicate<string Target, string Name, MCInstPredicate P> : MCInstPredicate {
|
||||||
|
string TargetName = Target;
|
||||||
|
string FunctionName = Name;
|
||||||
|
MCInstPredicate Pred = P;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A function predicate that takes as input a machine instruction, and returns
|
||||||
|
// a boolean value.
|
||||||
|
//
|
||||||
|
// This predicate is expanded into a function call by the PredicateExpander.
|
||||||
|
// In particular, the PredicateExpander would either expand this predicate into
|
||||||
|
// a call to `MCInstFn`, or into a call to`MachineInstrFn` depending on whether
|
||||||
|
// it is lowering predicates for MCInst or MachineInstr.
|
||||||
|
//
|
||||||
|
// In this context, `MCInstFn` and `MachineInstrFn` are both function names.
|
||||||
|
class CheckFunctionPredicate<string MCInstFn, string MachineInstrFn> : MCInstPredicate {
|
||||||
|
string MCInstFnName = MCInstFn;
|
||||||
|
string MachineInstrFnName = MachineInstrFn;
|
||||||
|
}
|
|
@ -355,13 +355,23 @@ class PredicateProlog<code c> {
|
||||||
code Code = c;
|
code Code = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Base class for scheduling predicates.
|
||||||
|
class SchedPredicateBase;
|
||||||
|
|
||||||
|
// A scheduling predicate whose logic is defined by a MCInstPredicate.
|
||||||
|
// This can directly be used by SchedWriteVariant definitions.
|
||||||
|
class MCSchedPredicate<MCInstPredicate P> : SchedPredicateBase {
|
||||||
|
MCInstPredicate Pred = P;
|
||||||
|
SchedMachineModel SchedModel = ?;
|
||||||
|
}
|
||||||
|
|
||||||
// Define a predicate to determine which SchedVariant applies to a
|
// Define a predicate to determine which SchedVariant applies to a
|
||||||
// particular MachineInstr. The code snippet is used as an
|
// particular MachineInstr. The code snippet is used as an
|
||||||
// if-statement's expression. Available variables are MI, SchedModel,
|
// if-statement's expression. Available variables are MI, SchedModel,
|
||||||
// and anything defined in a PredicateProlog.
|
// and anything defined in a PredicateProlog.
|
||||||
//
|
//
|
||||||
// SchedModel silences warnings but is ignored.
|
// SchedModel silences warnings but is ignored.
|
||||||
class SchedPredicate<code pred> {
|
class SchedPredicate<code pred> : SchedPredicateBase {
|
||||||
SchedMachineModel SchedModel = ?;
|
SchedMachineModel SchedModel = ?;
|
||||||
code Predicate = pred;
|
code Predicate = pred;
|
||||||
}
|
}
|
||||||
|
@ -376,8 +386,8 @@ def NoSchedPred : SchedPredicate<[{true}]>;
|
||||||
// operands. In this case, latency is not additive. If the current Variant
|
// operands. In this case, latency is not additive. If the current Variant
|
||||||
// is already part of a Sequence, then that entire chain leading up to
|
// is already part of a Sequence, then that entire chain leading up to
|
||||||
// the Variant is distributed over the variadic operands.
|
// the Variant is distributed over the variadic operands.
|
||||||
class SchedVar<SchedPredicate pred, list<SchedReadWrite> selected> {
|
class SchedVar<SchedPredicateBase pred, list<SchedReadWrite> selected> {
|
||||||
SchedPredicate Predicate = pred;
|
SchedPredicateBase Predicate = pred;
|
||||||
list<SchedReadWrite> Selected = selected;
|
list<SchedReadWrite> Selected = selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ add_tablegen(llvm-tblgen LLVM
|
||||||
InstrDocsEmitter.cpp
|
InstrDocsEmitter.cpp
|
||||||
IntrinsicEmitter.cpp
|
IntrinsicEmitter.cpp
|
||||||
OptParserEmitter.cpp
|
OptParserEmitter.cpp
|
||||||
|
PredicateExpander.cpp
|
||||||
PseudoLoweringEmitter.cpp
|
PseudoLoweringEmitter.cpp
|
||||||
RISCVCompressInstEmitter.cpp
|
RISCVCompressInstEmitter.cpp
|
||||||
RegisterBankEmitter.cpp
|
RegisterBankEmitter.cpp
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "CodeGenInstruction.h"
|
#include "CodeGenInstruction.h"
|
||||||
#include "CodeGenSchedule.h"
|
#include "CodeGenSchedule.h"
|
||||||
#include "CodeGenTarget.h"
|
#include "CodeGenTarget.h"
|
||||||
|
#include "PredicateExpander.h"
|
||||||
#include "SequenceToOffsetTable.h"
|
#include "SequenceToOffsetTable.h"
|
||||||
#include "TableGenBackends.h"
|
#include "TableGenBackends.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
@ -59,6 +60,13 @@ private:
|
||||||
typedef std::map<std::map<unsigned, unsigned>,
|
typedef std::map<std::map<unsigned, unsigned>,
|
||||||
std::vector<std::string>> OpNameMapTy;
|
std::vector<std::string>> OpNameMapTy;
|
||||||
typedef std::map<std::string, unsigned>::iterator StrUintMapIter;
|
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,
|
void emitRecord(const CodeGenInstruction &Inst, unsigned Num,
|
||||||
Record *InstrInfo,
|
Record *InstrInfo,
|
||||||
std::map<std::vector<Record*>, unsigned> &EL,
|
std::map<std::vector<Record*>, unsigned> &EL,
|
||||||
|
@ -339,6 +347,25 @@ void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS,
|
||||||
OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n\n";
|
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.
|
// Main Output.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -435,9 +462,11 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
|
||||||
OS << "struct " << ClassName << " : public TargetInstrInfo {\n"
|
OS << "struct " << ClassName << " : public TargetInstrInfo {\n"
|
||||||
<< " explicit " << ClassName
|
<< " explicit " << ClassName
|
||||||
<< "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1, int CatchRetOpcode = -1, int ReturnOpcode = -1);\n"
|
<< "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1, int CatchRetOpcode = -1, int ReturnOpcode = -1);\n"
|
||||||
<< " ~" << ClassName << "() override = default;\n"
|
<< " ~" << ClassName << "() override = default;\n";
|
||||||
<< "};\n";
|
|
||||||
OS << "} // end llvm namespace\n";
|
emitTIIHelperMethods(OS);
|
||||||
|
|
||||||
|
OS << "\n};\n} // end llvm namespace\n";
|
||||||
|
|
||||||
OS << "#endif // GET_INSTRINFO_HEADER\n\n";
|
OS << "#endif // GET_INSTRINFO_HEADER\n\n";
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "CodeGenTarget.h"
|
#include "CodeGenTarget.h"
|
||||||
#include "CodeGenSchedule.h"
|
#include "CodeGenSchedule.h"
|
||||||
|
#include "PredicateExpander.h"
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
|
@ -112,6 +113,9 @@ class SubtargetEmitter {
|
||||||
void EmitProcessorModels(raw_ostream &OS);
|
void EmitProcessorModels(raw_ostream &OS);
|
||||||
void EmitProcessorLookup(raw_ostream &OS);
|
void EmitProcessorLookup(raw_ostream &OS);
|
||||||
void EmitSchedModelHelpers(const std::string &ClassName, 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 EmitSchedModel(raw_ostream &OS);
|
||||||
void EmitHwModeCheck(const std::string &ClassName, raw_ostream &OS);
|
void EmitHwModeCheck(const std::string &ClassName, raw_ostream &OS);
|
||||||
void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
|
void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
|
||||||
|
@ -1461,35 +1465,37 @@ static void emitPredicateProlog(const RecordKeeper &Records, raw_ostream &OS) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void emitPredicates(const CodeGenSchedTransition &T,
|
static void emitPredicates(const CodeGenSchedTransition &T,
|
||||||
const CodeGenSchedClass &SC, unsigned ProcIdx,
|
const CodeGenSchedClass &SC,
|
||||||
|
PredicateExpander &PE,
|
||||||
raw_ostream &OS) {
|
raw_ostream &OS) {
|
||||||
if (ProcIdx && !count(T.ProcIndices, ProcIdx))
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::string Buffer;
|
std::string Buffer;
|
||||||
raw_string_ostream Stream(Buffer);
|
raw_string_ostream StringStream(Buffer);
|
||||||
Stream << " if (";
|
formatted_raw_ostream FOS(StringStream);
|
||||||
|
|
||||||
|
FOS.PadToColumn(6);
|
||||||
|
FOS << "if (";
|
||||||
for (RecIter RI = T.PredTerm.begin(), RE = T.PredTerm.end(); RI != RE; ++RI) {
|
for (RecIter RI = T.PredTerm.begin(), RE = T.PredTerm.end(); RI != RE; ++RI) {
|
||||||
if (RI != T.PredTerm.begin())
|
if (RI != T.PredTerm.begin()) {
|
||||||
Stream << "\n && ";
|
FOS << "\n";
|
||||||
Stream << "(" << (*RI)->getValueAsString("Predicate") << ")";
|
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"
|
FOS << ")\n";
|
||||||
<< " return " << T.ToClassIdx << "; // " << SC.Name << '\n';
|
FOS.PadToColumn(8);
|
||||||
Stream.flush();
|
FOS << "return " << T.ToClassIdx << "; // " << SC.Name << '\n';
|
||||||
|
FOS.flush();
|
||||||
OS << Buffer;
|
OS << Buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubtargetEmitter::EmitSchedModelHelpers(const std::string &ClassName,
|
void SubtargetEmitter::emitSchedModelHelpersImpl(
|
||||||
raw_ostream &OS) {
|
raw_ostream &OS, bool OnlyExpandMCInstPredicates) {
|
||||||
OS << "unsigned " << ClassName
|
|
||||||
<< "\n::resolveSchedClass(unsigned SchedClass, const MachineInstr *MI,"
|
|
||||||
<< " const TargetSchedModel *SchedModel) const {\n";
|
|
||||||
|
|
||||||
// Emit the predicate prolog code.
|
|
||||||
emitPredicateProlog(Records, OS);
|
|
||||||
|
|
||||||
// Collect Variant Classes.
|
// Collect Variant Classes.
|
||||||
IdxVec VariantClasses;
|
IdxVec VariantClasses;
|
||||||
for (const CodeGenSchedClass &SC : SchedModels.schedClasses()) {
|
for (const CodeGenSchedClass &SC : SchedModels.schedClasses()) {
|
||||||
|
@ -1503,24 +1509,43 @@ void SubtargetEmitter::EmitSchedModelHelpers(const std::string &ClassName,
|
||||||
for (unsigned VC : VariantClasses) {
|
for (unsigned VC : VariantClasses) {
|
||||||
// Emit code for each variant scheduling class.
|
// Emit code for each variant scheduling class.
|
||||||
const CodeGenSchedClass &SC = SchedModels.getSchedClass(VC);
|
const CodeGenSchedClass &SC = SchedModels.getSchedClass(VC);
|
||||||
OS << " case " << VC << ": // " << SC.Name << '\n';
|
|
||||||
IdxVec ProcIndices;
|
IdxVec ProcIndices;
|
||||||
for (const CodeGenSchedTransition &T : SC.Transitions) {
|
for (const CodeGenSchedTransition &T : SC.Transitions) {
|
||||||
|
if (OnlyExpandMCInstPredicates &&
|
||||||
|
!all_of(T.PredTerm, [](const Record *Rec) {
|
||||||
|
return Rec->isSubClassOf("MCSchedPredicate");
|
||||||
|
}))
|
||||||
|
continue;
|
||||||
|
|
||||||
IdxVec PI;
|
IdxVec PI;
|
||||||
std::set_union(T.ProcIndices.begin(), T.ProcIndices.end(),
|
std::set_union(T.ProcIndices.begin(), T.ProcIndices.end(),
|
||||||
ProcIndices.begin(), ProcIndices.end(),
|
ProcIndices.begin(), ProcIndices.end(),
|
||||||
std::back_inserter(PI));
|
std::back_inserter(PI));
|
||||||
ProcIndices.swap(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) {
|
for (unsigned PI : ProcIndices) {
|
||||||
OS << " ";
|
OS << " ";
|
||||||
if (PI != 0)
|
if (PI != 0) {
|
||||||
OS << "if (SchedModel->getProcessorID() == " << PI << ") ";
|
OS << (OnlyExpandMCInstPredicates
|
||||||
OS << "{ // " << (SchedModels.procModelBegin() + PI)->ModelName
|
? "if (CPUID == "
|
||||||
<< '\n';
|
: "if (SchedModel->getProcessorID() == ");
|
||||||
|
OS << PI << ") ";
|
||||||
|
}
|
||||||
|
OS << "{ // " << (SchedModels.procModelBegin() + PI)->ModelName << '\n';
|
||||||
|
|
||||||
for (const CodeGenSchedTransition &T : SC.Transitions)
|
for (const CodeGenSchedTransition &T : SC.Transitions) {
|
||||||
emitPredicates(T, SchedModels.getSchedClass(T.ToClassIdx), PI, OS);
|
if (PI != 0 && !count(T.ProcIndices, PI))
|
||||||
|
continue;
|
||||||
|
PE.setIndentLevel(4);
|
||||||
|
emitPredicates(T, SchedModels.getSchedClass(T.ToClassIdx), PE, OS);
|
||||||
|
}
|
||||||
|
|
||||||
OS << " }\n";
|
OS << " }\n";
|
||||||
if (PI == 0)
|
if (PI == 0)
|
||||||
|
@ -1532,8 +1557,29 @@ void SubtargetEmitter::EmitSchedModelHelpers(const std::string &ClassName,
|
||||||
}
|
}
|
||||||
OS << " };\n";
|
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,
|
void SubtargetEmitter::EmitHwModeCheck(const std::string &ClassName,
|
||||||
|
|
Loading…
Reference in New Issue