Index: include/llvm/CodeGen/TargetSchedule.h =================================================================== --- include/llvm/CodeGen/TargetSchedule.h +++ include/llvm/CodeGen/TargetSchedule.h @@ -116,6 +116,14 @@ return SchedModel.getProcResource(PIdx); } + /// Return the TargetId for the specified ProcResourceIdx. + /// The TargetId is a user defined value for the target that + /// can be used uniquely identify the type of a processor resource for an + /// architecture in C++ code. + int getProcResourceTargetId(unsigned ProcResourceIdx) const { + return SchedModel.getProcResourceTargetId(ProcResourceIdx); + } + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) const char *getResourceName(unsigned PIdx) const { if (!PIdx) Index: include/llvm/MC/MCSchedule.h =================================================================== --- include/llvm/MC/MCSchedule.h +++ include/llvm/MC/MCSchedule.h @@ -310,6 +310,7 @@ unsigned ProcID; const MCProcResourceDesc *ProcResourceTable; + const int *ProcResourceTargetIdTable; const MCSchedClassDesc *SchedClassTable; unsigned NumProcResourceKinds; unsigned NumSchedClasses; @@ -350,6 +351,17 @@ return &ProcResourceTable[ProcResourceIdx]; } + /// Return the TargetId for the specified ProcResourceIdx. + /// The TargetId is a user defined value for the target that + /// can be used uniquely identify the type of a processor resource for an + /// architecture in C++ code. + int getProcResourceTargetId(unsigned ProcResourceIdx) const { + assert(hasInstrSchedModel() && "No scheduling machine model"); + + assert(ProcResourceIdx < NumProcResourceKinds && "bad proc resource idx"); + return ProcResourceTargetIdTable[ProcResourceIdx]; + } + const MCSchedClassDesc *getSchedClassDesc(unsigned SchedClassIdx) const { assert(hasInstrSchedModel() && "No scheduling machine model"); Index: include/llvm/Target/TargetSchedule.td =================================================================== --- include/llvm/Target/TargetSchedule.td +++ include/llvm/Target/TargetSchedule.td @@ -198,12 +198,15 @@ // Subtargets typically define processor resource kind and number of // units in one place. class ProcResource : ProcResourceKind, - ProcResourceUnits; + ProcResourceUnits { + int TargetId = -1; +} class ProcResGroup resources> : ProcResourceKind { list Resources = resources; SchedMachineModel SchedModel = ?; int BufferSize = -1; + int TargetId = -1; } // A target architecture may define SchedReadWrite types and associate Index: lib/MC/MCSchedule.cpp =================================================================== --- lib/MC/MCSchedule.cpp +++ lib/MC/MCSchedule.cpp @@ -33,6 +33,7 @@ 0, nullptr, nullptr, + nullptr, 0, 0, nullptr, Index: test/TableGen/TargetIdTest.td =================================================================== --- /dev/null +++ test/TableGen/TargetIdTest.td @@ -0,0 +1,73 @@ +// RUN: llvm-tblgen -gen-subtarget -I %p/../../include %s -o - +// Check that the TargetId feature produces the expected output. + +include "llvm/Target/Target.td" + +def WriteFake : SchedWrite; +def WriteFake2 : SchedWrite; +def WriteFake3 : SchedWrite; + +def FakeModel : SchedMachineModel { + let LoadLatency = 100; + let HighLatency = 100; + + let IssueWidth = 1; + let MicroOpBufferSize = 0; + let CompleteModel = 0; +} + +def FakeUnit : ProcResource<1> { + let TargetId = 1; + let BufferSize = 0; +} + +def FakeUnit2 : ProcResource<1> { + let TargetId = 4; + let BufferSize = 0; +} + +def FakeUnit3 : ProcResource<1> { + let TargetId = 7; + let BufferSize = 0; +} + +def FakeUnit4 : ProcResource<1> { + let TargetId = 8; + let BufferSize = 0; +} + +let SchedModel = FakeModel in { +def : WriteRes { + let Latency = 10; + let ResourceCycles = [1, 2]; +} +def : WriteRes { + let Latency = 10; + let ResourceCycles = [1]; +} +def : WriteRes { + let Latency = 10; + let ResourceCycles = [1]; +} +} + +def : ProcessorModel<"fake", FakeModel, []>; +def FakeTarget : Target; + +// CHECK: // {Name, NumUnits, SuperIdx, BufferSize, SubUnitsIdxBegin} +// CHECK-NEXT: static const llvm::MCProcResourceDesc FakeModelProcResources[] = { +// CHECK-NEXT: {"InvalidUnit", 0, 0, 0, 0}, +// CHECK-NEXT: {"FakeUnit", 1, 0, 0, nullptr}, // #1 +// CHECK-NEXT: {"FakeUnit2", 1, 0, 0, nullptr}, // #2 +// CHECK-NEXT: {"FakeUnit3", 1, 0, 0, nullptr}, // #3 +// CHECK-NEXT: {"FakeUnit4", 1, 0, 0, nullptr}, // #4 +// CHECK-NEXT: }; +// CHECK-EMPTY: +// CHECK-NEXT: // {Id} +// CHECK-NEXT: static const int FakeModelProcResourcesTargetIds[] = { +// CHECK-NEXT: -1, +// CHECK-NEXT: 1, // #1 +// CHECK-NEXT: 4, // #2 +// CHECK-NEXT: 7, // #3 +// CHECK-NEXT: 8, // #4 +// CHECK-NEXT: }; Index: utils/TableGen/SubtargetEmitter.cpp =================================================================== --- utils/TableGen/SubtargetEmitter.cpp +++ utils/TableGen/SubtargetEmitter.cpp @@ -795,6 +795,7 @@ << " {\"InvalidUnit\", 0, 0, 0, 0},\n"; unsigned SubUnitsOffset = 1; + bool AnyTargetIdPresent = false; for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) { Record *PRDef = ProcModel.ProcResourceDefs[i]; @@ -820,6 +821,8 @@ } NumUnits = PRDef->getValueAsInt("NumUnits"); } + if (PRDef->getValueAsInt("TargetId") != -1) + AnyTargetIdPresent = true; // Emit the ProcResourceDesc OS << " {\"" << PRDef->getName() << "\", "; if (PRDef->getName().size() < 15) @@ -837,6 +840,20 @@ OS << "\n"; } OS << "};\n"; + // Emit TargetId table for processor if IDs are present + if (AnyTargetIdPresent) { + OS << "\n// {Id}\n"; + OS << "static const int " << ProcModel.ModelName << "ProcResourcesTargetIds" + << "[] = {\n" + << " -1," + << "\n"; + for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) { + Record *PRDef = ProcModel.ProcResourceDefs[i]; + int TargetId = PRDef->getValueAsInt("TargetId"); + OS << " " << TargetId << ", // #" << i + 1 << "\n"; + } + OS << "};\n"; + } } // Find the WriteRes Record that defines processor resources for this @@ -1384,14 +1401,29 @@ << "CompleteModel\n"; OS << " " << PM.Index << ", // Processor ID\n"; - if (PM.hasInstrSchedModel()) - OS << " " << PM.ModelName << "ProcResources" << ",\n" - << " " << PM.ModelName << "SchedClasses" << ",\n" - << " " << PM.ProcResourceDefs.size()+1 << ",\n" - << " " << (SchedModels.schedClassEnd() - - SchedModels.schedClassBegin()) << ",\n"; - else - OS << " nullptr, nullptr, 0, 0," + if (PM.hasInstrSchedModel()) { + bool HasProcResourceDefsId = false; + for (auto *PRG : PM.ProcResourceDefs) + if (PRG->getValueAsInt("TargetId") != -1) { + HasProcResourceDefsId = true; + break; + } + OS << " " << PM.ModelName << "ProcResources" + << ",\n"; + if (HasProcResourceDefsId) + OS << " " << PM.ModelName << "ProcResourcesTargetIds" + << ",\n"; + else + OS << " " + << "nullptr,\n"; + OS << " " << PM.ModelName << "SchedClasses" + << ",\n" + << " " << PM.ProcResourceDefs.size() + 1 << ",\n" + << " " + << (SchedModels.schedClassEnd() - SchedModels.schedClassBegin()) + << ",\n"; + } else + OS << " nullptr, nullptr, nullptr, 0, 0," << " // No instruction-level machine model.\n"; if (PM.hasItineraries()) OS << " " << PM.ItinsDef->getName() << ",\n";