diff --git a/llvm/include/llvm/MCA/HardwareUnits/ResourceManager.h b/llvm/include/llvm/MCA/HardwareUnits/ResourceManager.h index 66272af8a9f0..3addaaf47759 100644 --- a/llvm/include/llvm/MCA/HardwareUnits/ResourceManager.h +++ b/llvm/include/llvm/MCA/HardwareUnits/ResourceManager.h @@ -347,6 +347,9 @@ class ResourceManager { // Set of processor resource units that are available during this cycle. uint64_t AvailableProcResUnits; + // Set of processor resource groups that are currently reserved. + uint64_t ReservedResourceGroups; + // Returns the actual resource unit that will be used. ResourceRef selectPipe(uint64_t ResourceID); @@ -397,7 +400,7 @@ public: // Returns a zero mask if resources requested by Desc are all available during // this cycle. It returns a non-zero mask value only if there are unavailable // processor resources; each bit set in the mask represents a busy processor - // resource unit. + // resource unit or a reserved processor resource group. uint64_t checkAvailability(const InstrDesc &Desc) const; uint64_t getProcResUnitMask() const { return ProcResUnitMask; } diff --git a/llvm/include/llvm/MCA/Instruction.h b/llvm/include/llvm/MCA/Instruction.h index 0fba938560d7..658b7fe4f891 100644 --- a/llvm/include/llvm/MCA/Instruction.h +++ b/llvm/include/llvm/MCA/Instruction.h @@ -338,6 +338,9 @@ struct InstrDesc { // A list of buffered resources consumed by this instruction. SmallVector Buffers; + unsigned UsedProcResUnits; + unsigned UsedProcResGroups; + unsigned MaxLatency; // Number of MicroOps for this instruction. unsigned NumMicroOps; diff --git a/llvm/lib/MCA/HardwareUnits/ResourceManager.cpp b/llvm/lib/MCA/HardwareUnits/ResourceManager.cpp index da6bfd553391..21e0271c8525 100644 --- a/llvm/lib/MCA/HardwareUnits/ResourceManager.cpp +++ b/llvm/lib/MCA/HardwareUnits/ResourceManager.cpp @@ -118,8 +118,8 @@ ResourceManager::ResourceManager(const MCSchedModel &SM) : Resources(SM.getNumProcResourceKinds()), Strategies(SM.getNumProcResourceKinds()), Resource2Groups(SM.getNumProcResourceKinds(), 0), - ProcResID2Mask(SM.getNumProcResourceKinds()), - ProcResUnitMask(0) { + ProcResID2Mask(SM.getNumProcResourceKinds()), ProcResUnitMask(0), + ReservedResourceGroups(0) { computeProcResourceMasks(SM, ProcResID2Mask); for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) { @@ -278,7 +278,10 @@ uint64_t ResourceManager::checkAvailability(const InstrDesc &Desc) const { BusyResourceMask |= E.first; } - return BusyResourceMask & ProcResUnitMask; + BusyResourceMask &= ProcResUnitMask; + if (BusyResourceMask) + return BusyResourceMask; + return Desc.UsedProcResGroups & ReservedResourceGroups; } void ResourceManager::issueInstruction( @@ -330,13 +333,17 @@ void ResourceManager::cycleEvent(SmallVectorImpl &ResourcesFreed) { void ResourceManager::reserveResource(uint64_t ResourceID) { ResourceState &Resource = *Resources[getResourceStateIndex(ResourceID)]; - assert(!Resource.isReserved()); + assert(Resource.isAResourceGroup() && !Resource.isReserved() && + "Unexpected resource found!"); Resource.setReserved(); + ReservedResourceGroups ^= PowerOf2Floor(ResourceID); } void ResourceManager::releaseResource(uint64_t ResourceID) { ResourceState &Resource = *Resources[getResourceStateIndex(ResourceID)]; Resource.clearReserved(); + if (Resource.isAResourceGroup()) + ReservedResourceGroups ^= PowerOf2Floor(ResourceID); } } // namespace mca diff --git a/llvm/lib/MCA/InstrBuilder.cpp b/llvm/lib/MCA/InstrBuilder.cpp index 1e08f8985236..e10efb28f775 100644 --- a/llvm/lib/MCA/InstrBuilder.cpp +++ b/llvm/lib/MCA/InstrBuilder.cpp @@ -97,14 +97,14 @@ static void initializeUsedResources(InstrDesc &ID, }); uint64_t UsedResourceUnits = 0; + uint64_t UsedResourceGroups = 0; // Remove cycles contributed by smaller resources. for (unsigned I = 0, E = Worklist.size(); I < E; ++I) { ResourcePlusCycles &A = Worklist[I]; if (!A.second.size()) { - A.second.NumUnits = 0; - A.second.setReserved(); - ID.Resources.emplace_back(A); + assert(countPopulation(A.first) > 1 && "Expected a group!"); + UsedResourceGroups |= PowerOf2Floor(A.first); continue; } @@ -127,6 +127,9 @@ static void initializeUsedResources(InstrDesc &ID, } } + ID.UsedProcResUnits = UsedResourceUnits; + ID.UsedProcResGroups = UsedResourceGroups; + // A SchedWrite may specify a number of cycles in which a resource group // is reserved. For example (on target x86; cpu Haswell): // @@ -179,10 +182,14 @@ static void initializeUsedResources(InstrDesc &ID, LLVM_DEBUG({ for (const std::pair &R : ID.Resources) - dbgs() << "\t\tMask=" << format_hex(R.first, 16) << ", " + dbgs() << "\t\tResource Mask=" << format_hex(R.first, 16) << ", " + << "Reserved=" << R.second.isReserved() << ", " + << "#Units=" << R.second.NumUnits << ", " << "cy=" << R.second.size() << '\n'; for (const uint64_t R : ID.Buffers) dbgs() << "\t\tBuffer Mask=" << format_hex(R, 16) << '\n'; + dbgs() << "\t\t Used Units=" << format_hex(ID.UsedProcResUnits, 16) << '\n'; + dbgs() << "\t\tUsed Groups=" << format_hex(ID.UsedProcResGroups, 16) << '\n'; }); }