Index: llvm/trunk/include/llvm/CodeGen/TargetSchedule.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/TargetSchedule.h +++ llvm/trunk/include/llvm/CodeGen/TargetSchedule.h @@ -185,6 +185,7 @@ /// if converter after moving it to TargetSchedModel). unsigned computeInstrLatency(const MachineInstr *MI, bool UseDefaultDefLatency = true) const; + unsigned computeInstrLatency(const MCInst &MI) const; unsigned computeInstrLatency(unsigned Opcode) const; @@ -196,6 +197,7 @@ /// Compute the reciprocal throughput of the given instruction. Optional computeReciprocalThroughput(const MachineInstr *MI) const; + Optional computeReciprocalThroughput(const MCInst &MI) const; Optional computeReciprocalThroughput(unsigned Opcode) const; }; Index: llvm/trunk/include/llvm/MC/MCSchedule.h =================================================================== --- llvm/trunk/include/llvm/MC/MCSchedule.h +++ llvm/trunk/include/llvm/MC/MCSchedule.h @@ -25,6 +25,7 @@ struct InstrItinerary; class MCSubtargetInfo; class MCInstrInfo; +class MCInst; class InstrItineraryData; /// Define a kind of processor resource that will be modeled by the scheduler. @@ -357,6 +358,8 @@ const MCSchedClassDesc &SCDesc); int computeInstrLatency(const MCSubtargetInfo &STI, unsigned SClass) const; + int computeInstrLatency(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, + const MCInst &Inst) const; // Returns the reciprocal throughput information from a MCSchedClassDesc. static Optional @@ -366,6 +369,10 @@ static Optional getReciprocalThroughput(unsigned SchedClass, const InstrItineraryData &IID); + Optional + getReciprocalThroughput(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, + const MCInst &Inst) const; + /// Returns the default initialized model. static const MCSchedModel &GetDefaultSchedModel() { return Default; } static const MCSchedModel Default; Index: llvm/trunk/lib/CodeGen/TargetSchedule.cpp =================================================================== --- llvm/trunk/lib/CodeGen/TargetSchedule.cpp +++ llvm/trunk/lib/CodeGen/TargetSchedule.cpp @@ -261,7 +261,13 @@ unsigned TargetSchedModel::computeInstrLatency(unsigned Opcode) const { assert(hasInstrSchedModel() && "Only call this function with a SchedModel"); unsigned SCIdx = TII->get(Opcode).getSchedClass(); - return SchedModel.computeInstrLatency(*STI, SCIdx); + return capLatency(SchedModel.computeInstrLatency(*STI, SCIdx)); +} + +unsigned TargetSchedModel::computeInstrLatency(const MCInst &Inst) const { + if (hasInstrSchedModel()) + return capLatency(SchedModel.computeInstrLatency(*STI, *TII, Inst)); + return computeInstrLatency(Inst.getOpcode()); } unsigned @@ -342,3 +348,11 @@ } return Optional(); } + +Optional +TargetSchedModel::computeReciprocalThroughput(const MCInst &MI) const { + if (hasInstrSchedModel()) + return SchedModel.getReciprocalThroughput(*STI, *TII, MI); + return computeReciprocalThroughput(MI.getOpcode()); +} + Index: llvm/trunk/lib/CodeGen/TargetSubtargetInfo.cpp =================================================================== --- llvm/trunk/lib/CodeGen/TargetSubtargetInfo.cpp +++ llvm/trunk/lib/CodeGen/TargetSubtargetInfo.cpp @@ -102,7 +102,7 @@ TSchedModel.init(this); unsigned Latency; if (TSchedModel.hasInstrSchedModel()) - Latency = TSchedModel.computeInstrLatency(MCI.getOpcode()); + Latency = TSchedModel.computeInstrLatency(MCI); else if (TSchedModel.hasInstrItineraries()) { auto *ItinData = TSchedModel.getInstrItineraries(); Latency = ItinData->getStageLatency( @@ -110,7 +110,7 @@ } else return std::string(); Optional RThroughput = - TSchedModel.computeReciprocalThroughput(MCI.getOpcode()); + TSchedModel.computeReciprocalThroughput(MCI); return createSchedInfoStr(Latency, RThroughput); } Index: llvm/trunk/lib/MC/MCSchedule.cpp =================================================================== --- llvm/trunk/lib/MC/MCSchedule.cpp +++ llvm/trunk/lib/MC/MCSchedule.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCSchedule.h" +#include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -64,6 +65,26 @@ llvm_unreachable("unsupported variant scheduling class"); } +int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI, + const MCInstrInfo &MCII, + const MCInst &Inst) const { + unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass(); + const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass); + if (!SCDesc->isValid()) + return 0; + + unsigned CPUID = getProcessorID(); + while (SCDesc->isVariant()) { + SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, CPUID); + SCDesc = getSchedClassDesc(SchedClass); + } + + if (SchedClass) + return MCSchedModel::computeInstrLatency(STI, *SCDesc); + + llvm_unreachable("unsupported variant scheduling class"); +} + Optional MCSchedModel::getReciprocalThroughput(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc) { @@ -82,6 +103,28 @@ } Optional +MCSchedModel::getReciprocalThroughput(const MCSubtargetInfo &STI, + const MCInstrInfo &MCII, + const MCInst &Inst) const { + Optional Throughput; + unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass(); + const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass); + if (!SCDesc->isValid()) + return Throughput; + + unsigned CPUID = getProcessorID(); + while (SCDesc->isVariant()) { + SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, CPUID); + SCDesc = getSchedClassDesc(SchedClass); + } + + if (SchedClass) + return MCSchedModel::getReciprocalThroughput(STI, *SCDesc); + + llvm_unreachable("unsupported variant scheduling class"); +} + +Optional MCSchedModel::getReciprocalThroughput(unsigned SchedClass, const InstrItineraryData &IID) { Optional Throughput; Index: llvm/trunk/utils/TableGen/SubtargetEmitter.cpp =================================================================== --- llvm/trunk/utils/TableGen/SubtargetEmitter.cpp +++ llvm/trunk/utils/TableGen/SubtargetEmitter.cpp @@ -1587,8 +1587,15 @@ // Emit target predicates. emitSchedModelHelpersImpl(OS); + + OS << "} // " << ClassName << "::resolveSchedClass\n\n"; - OS << "} // " << ClassName << "::resolveSchedClass\n"; + OS << "unsigned " << ClassName + << "\n::resolveVariantSchedClass(unsigned SchedClass, const MCInst *MI," + << " unsigned CPUID) const {\n" + << " return " << Target << "_MC" + << "::resolveVariantSchedClassImpl(SchedClass, MI, CPUID);\n" + << "} // " << ClassName << "::resolveVariantSchedClass\n"; } void SubtargetEmitter::EmitHwModeCheck(const std::string &ClassName, @@ -1655,6 +1662,13 @@ } void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) { + OS << "namespace " << Target << "_MC {\n" + << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass,\n" + << " const MCInst *MI, unsigned CPUID) {\n"; + emitSchedModelHelpersImpl(OS, /* OnlyExpandMCPredicates */ true); + OS << "}\n"; + OS << "} // end of namespace " << Target << "_MC\n\n"; + OS << "struct " << Target << "GenMCSubtargetInfo : public MCSubtargetInfo {\n"; OS << " " << Target << "GenMCSubtargetInfo(const Triple &TT, \n" @@ -1668,8 +1682,9 @@ << " MCSubtargetInfo(TT, CPU, FS, PF, PD, ProcSched,\n" << " WPR, WL, RA, IS, OC, FP) { }\n\n" << " unsigned resolveVariantSchedClass(unsigned SchedClass,\n" - << " const MCInst *MI, unsigned CPUID) const override {\n"; - emitSchedModelHelpersImpl(OS, /* OnlyExpandMCPredicates */ true); + << " const MCInst *MI, unsigned CPUID) const override {\n" + << " return " << Target << "_MC" + << "::resolveVariantSchedClassImpl(SchedClass, MI, CPUID); \n"; OS << " }\n"; OS << "};\n"; } @@ -1754,6 +1769,10 @@ std::string ClassName = Target + "GenSubtargetInfo"; OS << "namespace llvm {\n"; OS << "class DFAPacketizer;\n"; + OS << "namespace " << Target << "_MC {\n" + << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass," + << " const MCInst *MI, unsigned CPUID);\n" + << "}\n\n"; OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n" << " explicit " << ClassName << "(const Triple &TT, StringRef CPU, " << "StringRef FS);\n" @@ -1761,6 +1780,8 @@ << " unsigned resolveSchedClass(unsigned SchedClass, " << " const MachineInstr *DefMI," << " const TargetSchedModel *SchedModel) const override;\n" + << " unsigned resolveVariantSchedClass(unsigned SchedClass," + << " const MCInst *MI, unsigned CPUID) const override;\n" << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)" << " const;\n"; if (TGT.getHwModes().getNumModeIds() > 1)