10b57cec5SDimitry Andric //===--------------------- ResourceManager.cpp ------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// \file 90b57cec5SDimitry Andric /// 100b57cec5SDimitry Andric /// The classes here represent processor resource units and their management 110b57cec5SDimitry Andric /// strategy. These classes are managed by the Scheduler. 120b57cec5SDimitry Andric /// 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "llvm/MCA/HardwareUnits/ResourceManager.h" 160b57cec5SDimitry Andric #include "llvm/MCA/Support.h" 170b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 180b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric namespace llvm { 210b57cec5SDimitry Andric namespace mca { 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric #define DEBUG_TYPE "llvm-mca" 240b57cec5SDimitry Andric ResourceStrategy::~ResourceStrategy() = default; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric static uint64_t selectImpl(uint64_t CandidateMask, 270b57cec5SDimitry Andric uint64_t &NextInSequenceMask) { 280b57cec5SDimitry Andric // The upper bit set in CandidateMask identifies our next candidate resource. 290b57cec5SDimitry Andric CandidateMask = 1ULL << getResourceStateIndex(CandidateMask); 300b57cec5SDimitry Andric NextInSequenceMask &= (CandidateMask | (CandidateMask - 1)); 310b57cec5SDimitry Andric return CandidateMask; 320b57cec5SDimitry Andric } 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric uint64_t DefaultResourceStrategy::select(uint64_t ReadyMask) { 350b57cec5SDimitry Andric // This method assumes that ReadyMask cannot be zero. 360b57cec5SDimitry Andric uint64_t CandidateMask = ReadyMask & NextInSequenceMask; 370b57cec5SDimitry Andric if (CandidateMask) 380b57cec5SDimitry Andric return selectImpl(CandidateMask, NextInSequenceMask); 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric NextInSequenceMask = ResourceUnitMask ^ RemovedFromNextInSequence; 410b57cec5SDimitry Andric RemovedFromNextInSequence = 0; 420b57cec5SDimitry Andric CandidateMask = ReadyMask & NextInSequenceMask; 430b57cec5SDimitry Andric if (CandidateMask) 440b57cec5SDimitry Andric return selectImpl(CandidateMask, NextInSequenceMask); 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric NextInSequenceMask = ResourceUnitMask; 470b57cec5SDimitry Andric CandidateMask = ReadyMask & NextInSequenceMask; 480b57cec5SDimitry Andric return selectImpl(CandidateMask, NextInSequenceMask); 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric void DefaultResourceStrategy::used(uint64_t Mask) { 520b57cec5SDimitry Andric if (Mask > NextInSequenceMask) { 530b57cec5SDimitry Andric RemovedFromNextInSequence |= Mask; 540b57cec5SDimitry Andric return; 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric NextInSequenceMask &= (~Mask); 580b57cec5SDimitry Andric if (NextInSequenceMask) 590b57cec5SDimitry Andric return; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric NextInSequenceMask = ResourceUnitMask ^ RemovedFromNextInSequence; 620b57cec5SDimitry Andric RemovedFromNextInSequence = 0; 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric ResourceState::ResourceState(const MCProcResourceDesc &Desc, unsigned Index, 660b57cec5SDimitry Andric uint64_t Mask) 670b57cec5SDimitry Andric : ProcResourceDescIndex(Index), ResourceMask(Mask), 680b57cec5SDimitry Andric BufferSize(Desc.BufferSize), IsAGroup(countPopulation(ResourceMask) > 1) { 690b57cec5SDimitry Andric if (IsAGroup) { 700b57cec5SDimitry Andric ResourceSizeMask = 710b57cec5SDimitry Andric ResourceMask ^ 1ULL << getResourceStateIndex(ResourceMask); 720b57cec5SDimitry Andric } else { 730b57cec5SDimitry Andric ResourceSizeMask = (1ULL << Desc.NumUnits) - 1; 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric ReadyMask = ResourceSizeMask; 760b57cec5SDimitry Andric AvailableSlots = BufferSize == -1 ? 0U : static_cast<unsigned>(BufferSize); 770b57cec5SDimitry Andric Unavailable = false; 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric bool ResourceState::isReady(unsigned NumUnits) const { 810b57cec5SDimitry Andric return (!isReserved() || isADispatchHazard()) && 820b57cec5SDimitry Andric countPopulation(ReadyMask) >= NumUnits; 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric ResourceStateEvent ResourceState::isBufferAvailable() const { 860b57cec5SDimitry Andric if (isADispatchHazard() && isReserved()) 870b57cec5SDimitry Andric return RS_RESERVED; 880b57cec5SDimitry Andric if (!isBuffered() || AvailableSlots) 890b57cec5SDimitry Andric return RS_BUFFER_AVAILABLE; 900b57cec5SDimitry Andric return RS_BUFFER_UNAVAILABLE; 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric #ifndef NDEBUG 940b57cec5SDimitry Andric void ResourceState::dump() const { 950b57cec5SDimitry Andric dbgs() << "MASK=" << format_hex(ResourceMask, 16) 960b57cec5SDimitry Andric << ", SZMASK=" << format_hex(ResourceSizeMask, 16) 970b57cec5SDimitry Andric << ", RDYMASK=" << format_hex(ReadyMask, 16) 980b57cec5SDimitry Andric << ", BufferSize=" << BufferSize 990b57cec5SDimitry Andric << ", AvailableSlots=" << AvailableSlots 1000b57cec5SDimitry Andric << ", Reserved=" << Unavailable << '\n'; 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric #endif 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric static std::unique_ptr<ResourceStrategy> 1050b57cec5SDimitry Andric getStrategyFor(const ResourceState &RS) { 1060b57cec5SDimitry Andric if (RS.isAResourceGroup() || RS.getNumUnits() > 1) 107*8bcb0991SDimitry Andric return std::make_unique<DefaultResourceStrategy>(RS.getReadyMask()); 1080b57cec5SDimitry Andric return std::unique_ptr<ResourceStrategy>(nullptr); 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric ResourceManager::ResourceManager(const MCSchedModel &SM) 1120b57cec5SDimitry Andric : Resources(SM.getNumProcResourceKinds() - 1), 1130b57cec5SDimitry Andric Strategies(SM.getNumProcResourceKinds() - 1), 1140b57cec5SDimitry Andric Resource2Groups(SM.getNumProcResourceKinds() - 1, 0), 1150b57cec5SDimitry Andric ProcResID2Mask(SM.getNumProcResourceKinds(), 0), 1160b57cec5SDimitry Andric ResIndex2ProcResID(SM.getNumProcResourceKinds() - 1, 0), 117*8bcb0991SDimitry Andric ProcResUnitMask(0), ReservedResourceGroups(0), 118*8bcb0991SDimitry Andric AvailableBuffers(~0ULL), ReservedBuffers(0) { 1190b57cec5SDimitry Andric computeProcResourceMasks(SM, ProcResID2Mask); 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric // initialize vector ResIndex2ProcResID. 1220b57cec5SDimitry Andric for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) { 1230b57cec5SDimitry Andric unsigned Index = getResourceStateIndex(ProcResID2Mask[I]); 1240b57cec5SDimitry Andric ResIndex2ProcResID[Index] = I; 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) { 1280b57cec5SDimitry Andric uint64_t Mask = ProcResID2Mask[I]; 1290b57cec5SDimitry Andric unsigned Index = getResourceStateIndex(Mask); 1300b57cec5SDimitry Andric Resources[Index] = 131*8bcb0991SDimitry Andric std::make_unique<ResourceState>(*SM.getProcResource(I), I, Mask); 1320b57cec5SDimitry Andric Strategies[Index] = getStrategyFor(*Resources[Index]); 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) { 1360b57cec5SDimitry Andric uint64_t Mask = ProcResID2Mask[I]; 1370b57cec5SDimitry Andric unsigned Index = getResourceStateIndex(Mask); 1380b57cec5SDimitry Andric const ResourceState &RS = *Resources[Index]; 1390b57cec5SDimitry Andric if (!RS.isAResourceGroup()) { 1400b57cec5SDimitry Andric ProcResUnitMask |= Mask; 1410b57cec5SDimitry Andric continue; 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric uint64_t GroupMaskIdx = 1ULL << Index; 1450b57cec5SDimitry Andric Mask -= GroupMaskIdx; 1460b57cec5SDimitry Andric while (Mask) { 1470b57cec5SDimitry Andric // Extract lowest set isolated bit. 1480b57cec5SDimitry Andric uint64_t Unit = Mask & (-Mask); 1490b57cec5SDimitry Andric unsigned IndexUnit = getResourceStateIndex(Unit); 1500b57cec5SDimitry Andric Resource2Groups[IndexUnit] |= GroupMaskIdx; 1510b57cec5SDimitry Andric Mask ^= Unit; 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric AvailableProcResUnits = ProcResUnitMask; 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric void ResourceManager::setCustomStrategyImpl(std::unique_ptr<ResourceStrategy> S, 1590b57cec5SDimitry Andric uint64_t ResourceMask) { 1600b57cec5SDimitry Andric unsigned Index = getResourceStateIndex(ResourceMask); 1610b57cec5SDimitry Andric assert(Index < Resources.size() && "Invalid processor resource index!"); 1620b57cec5SDimitry Andric assert(S && "Unexpected null strategy in input!"); 1630b57cec5SDimitry Andric Strategies[Index] = std::move(S); 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric unsigned ResourceManager::resolveResourceMask(uint64_t Mask) const { 1670b57cec5SDimitry Andric return ResIndex2ProcResID[getResourceStateIndex(Mask)]; 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric unsigned ResourceManager::getNumUnits(uint64_t ResourceID) const { 1710b57cec5SDimitry Andric return Resources[getResourceStateIndex(ResourceID)]->getNumUnits(); 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric // Returns the actual resource consumed by this Use. 1750b57cec5SDimitry Andric // First, is the primary resource ID. 1760b57cec5SDimitry Andric // Second, is the specific sub-resource ID. 1770b57cec5SDimitry Andric ResourceRef ResourceManager::selectPipe(uint64_t ResourceID) { 1780b57cec5SDimitry Andric unsigned Index = getResourceStateIndex(ResourceID); 1790b57cec5SDimitry Andric assert(Index < Resources.size() && "Invalid resource use!"); 1800b57cec5SDimitry Andric ResourceState &RS = *Resources[Index]; 1810b57cec5SDimitry Andric assert(RS.isReady() && "No available units to select!"); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric // Special case where RS is not a group, and it only declares a single 1840b57cec5SDimitry Andric // resource unit. 1850b57cec5SDimitry Andric if (!RS.isAResourceGroup() && RS.getNumUnits() == 1) 1860b57cec5SDimitry Andric return std::make_pair(ResourceID, RS.getReadyMask()); 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric uint64_t SubResourceID = Strategies[Index]->select(RS.getReadyMask()); 1890b57cec5SDimitry Andric if (RS.isAResourceGroup()) 1900b57cec5SDimitry Andric return selectPipe(SubResourceID); 1910b57cec5SDimitry Andric return std::make_pair(ResourceID, SubResourceID); 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric void ResourceManager::use(const ResourceRef &RR) { 1950b57cec5SDimitry Andric // Mark the sub-resource referenced by RR as used. 1960b57cec5SDimitry Andric unsigned RSID = getResourceStateIndex(RR.first); 1970b57cec5SDimitry Andric ResourceState &RS = *Resources[RSID]; 1980b57cec5SDimitry Andric RS.markSubResourceAsUsed(RR.second); 1990b57cec5SDimitry Andric // Remember to update the resource strategy for non-group resources with 2000b57cec5SDimitry Andric // multiple units. 2010b57cec5SDimitry Andric if (RS.getNumUnits() > 1) 2020b57cec5SDimitry Andric Strategies[RSID]->used(RR.second); 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric // If there are still available units in RR.first, 2050b57cec5SDimitry Andric // then we are done. 2060b57cec5SDimitry Andric if (RS.isReady()) 2070b57cec5SDimitry Andric return; 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric AvailableProcResUnits ^= RR.first; 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric // Notify groups that RR.first is no longer available. 2120b57cec5SDimitry Andric uint64_t Users = Resource2Groups[RSID]; 2130b57cec5SDimitry Andric while (Users) { 2140b57cec5SDimitry Andric // Extract lowest set isolated bit. 2150b57cec5SDimitry Andric unsigned GroupIndex = getResourceStateIndex(Users & (-Users)); 2160b57cec5SDimitry Andric ResourceState &CurrentUser = *Resources[GroupIndex]; 2170b57cec5SDimitry Andric CurrentUser.markSubResourceAsUsed(RR.first); 2180b57cec5SDimitry Andric Strategies[GroupIndex]->used(RR.first); 2190b57cec5SDimitry Andric // Reset lowest set bit. 2200b57cec5SDimitry Andric Users &= Users - 1; 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric void ResourceManager::release(const ResourceRef &RR) { 2250b57cec5SDimitry Andric unsigned RSID = getResourceStateIndex(RR.first); 2260b57cec5SDimitry Andric ResourceState &RS = *Resources[RSID]; 2270b57cec5SDimitry Andric bool WasFullyUsed = !RS.isReady(); 2280b57cec5SDimitry Andric RS.releaseSubResource(RR.second); 2290b57cec5SDimitry Andric if (!WasFullyUsed) 2300b57cec5SDimitry Andric return; 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric AvailableProcResUnits ^= RR.first; 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric // Notify groups that RR.first is now available again. 2350b57cec5SDimitry Andric uint64_t Users = Resource2Groups[RSID]; 2360b57cec5SDimitry Andric while (Users) { 2370b57cec5SDimitry Andric unsigned GroupIndex = getResourceStateIndex(Users & (-Users)); 2380b57cec5SDimitry Andric ResourceState &CurrentUser = *Resources[GroupIndex]; 2390b57cec5SDimitry Andric CurrentUser.releaseSubResource(RR.first); 2400b57cec5SDimitry Andric Users &= Users - 1; 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric ResourceStateEvent 245*8bcb0991SDimitry Andric ResourceManager::canBeDispatched(uint64_t ConsumedBuffers) const { 246*8bcb0991SDimitry Andric if (ConsumedBuffers & ReservedBuffers) 247*8bcb0991SDimitry Andric return ResourceStateEvent::RS_RESERVED; 248*8bcb0991SDimitry Andric if (ConsumedBuffers & (~AvailableBuffers)) 249*8bcb0991SDimitry Andric return ResourceStateEvent::RS_BUFFER_UNAVAILABLE; 250*8bcb0991SDimitry Andric return ResourceStateEvent::RS_BUFFER_AVAILABLE; 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 253*8bcb0991SDimitry Andric void ResourceManager::reserveBuffers(uint64_t ConsumedBuffers) { 254*8bcb0991SDimitry Andric while (ConsumedBuffers) { 255*8bcb0991SDimitry Andric uint64_t CurrentBuffer = ConsumedBuffers & (-ConsumedBuffers); 256*8bcb0991SDimitry Andric ResourceState &RS = *Resources[getResourceStateIndex(CurrentBuffer)]; 257*8bcb0991SDimitry Andric ConsumedBuffers ^= CurrentBuffer; 2580b57cec5SDimitry Andric assert(RS.isBufferAvailable() == ResourceStateEvent::RS_BUFFER_AVAILABLE); 259*8bcb0991SDimitry Andric if (!RS.reserveBuffer()) 260*8bcb0991SDimitry Andric AvailableBuffers ^= CurrentBuffer; 2610b57cec5SDimitry Andric if (RS.isADispatchHazard()) { 262*8bcb0991SDimitry Andric // Reserve this buffer now, and release it once pipeline resources 263*8bcb0991SDimitry Andric // consumed by the instruction become available again. 264*8bcb0991SDimitry Andric // We do this to simulate an in-order dispatch/issue of instructions. 265*8bcb0991SDimitry Andric ReservedBuffers ^= CurrentBuffer; 2660b57cec5SDimitry Andric } 2670b57cec5SDimitry Andric } 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric 270*8bcb0991SDimitry Andric void ResourceManager::releaseBuffers(uint64_t ConsumedBuffers) { 271*8bcb0991SDimitry Andric AvailableBuffers |= ConsumedBuffers; 272*8bcb0991SDimitry Andric while (ConsumedBuffers) { 273*8bcb0991SDimitry Andric uint64_t CurrentBuffer = ConsumedBuffers & (-ConsumedBuffers); 274*8bcb0991SDimitry Andric ResourceState &RS = *Resources[getResourceStateIndex(CurrentBuffer)]; 275*8bcb0991SDimitry Andric ConsumedBuffers ^= CurrentBuffer; 276*8bcb0991SDimitry Andric RS.releaseBuffer(); 277*8bcb0991SDimitry Andric // Do not unreserve dispatch hazard resource buffers. Wait until all 278*8bcb0991SDimitry Andric // pipeline resources have been freed too. 279*8bcb0991SDimitry Andric } 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric uint64_t ResourceManager::checkAvailability(const InstrDesc &Desc) const { 2830b57cec5SDimitry Andric uint64_t BusyResourceMask = 0; 2840b57cec5SDimitry Andric for (const std::pair<uint64_t, const ResourceUsage> &E : Desc.Resources) { 2850b57cec5SDimitry Andric unsigned NumUnits = E.second.isReserved() ? 0U : E.second.NumUnits; 2860b57cec5SDimitry Andric unsigned Index = getResourceStateIndex(E.first); 2870b57cec5SDimitry Andric if (!Resources[Index]->isReady(NumUnits)) 2880b57cec5SDimitry Andric BusyResourceMask |= E.first; 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric BusyResourceMask &= ProcResUnitMask; 2920b57cec5SDimitry Andric if (BusyResourceMask) 2930b57cec5SDimitry Andric return BusyResourceMask; 2940b57cec5SDimitry Andric return Desc.UsedProcResGroups & ReservedResourceGroups; 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric void ResourceManager::issueInstruction( 2980b57cec5SDimitry Andric const InstrDesc &Desc, 2990b57cec5SDimitry Andric SmallVectorImpl<std::pair<ResourceRef, ResourceCycles>> &Pipes) { 3000b57cec5SDimitry Andric for (const std::pair<uint64_t, ResourceUsage> &R : Desc.Resources) { 3010b57cec5SDimitry Andric const CycleSegment &CS = R.second.CS; 3020b57cec5SDimitry Andric if (!CS.size()) { 3030b57cec5SDimitry Andric releaseResource(R.first); 3040b57cec5SDimitry Andric continue; 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric assert(CS.begin() == 0 && "Invalid {Start, End} cycles!"); 3080b57cec5SDimitry Andric if (!R.second.isReserved()) { 3090b57cec5SDimitry Andric ResourceRef Pipe = selectPipe(R.first); 3100b57cec5SDimitry Andric use(Pipe); 3110b57cec5SDimitry Andric BusyResources[Pipe] += CS.size(); 3120b57cec5SDimitry Andric Pipes.emplace_back(std::pair<ResourceRef, ResourceCycles>( 3130b57cec5SDimitry Andric Pipe, ResourceCycles(CS.size()))); 3140b57cec5SDimitry Andric } else { 3150b57cec5SDimitry Andric assert((countPopulation(R.first) > 1) && "Expected a group!"); 3160b57cec5SDimitry Andric // Mark this group as reserved. 3170b57cec5SDimitry Andric assert(R.second.isReserved()); 3180b57cec5SDimitry Andric reserveResource(R.first); 3190b57cec5SDimitry Andric BusyResources[ResourceRef(R.first, R.first)] += CS.size(); 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric void ResourceManager::cycleEvent(SmallVectorImpl<ResourceRef> &ResourcesFreed) { 3250b57cec5SDimitry Andric for (std::pair<ResourceRef, unsigned> &BR : BusyResources) { 3260b57cec5SDimitry Andric if (BR.second) 3270b57cec5SDimitry Andric BR.second--; 3280b57cec5SDimitry Andric if (!BR.second) { 3290b57cec5SDimitry Andric // Release this resource. 3300b57cec5SDimitry Andric const ResourceRef &RR = BR.first; 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric if (countPopulation(RR.first) == 1) 3330b57cec5SDimitry Andric release(RR); 3340b57cec5SDimitry Andric releaseResource(RR.first); 3350b57cec5SDimitry Andric ResourcesFreed.push_back(RR); 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric for (const ResourceRef &RF : ResourcesFreed) 3400b57cec5SDimitry Andric BusyResources.erase(RF); 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric void ResourceManager::reserveResource(uint64_t ResourceID) { 3440b57cec5SDimitry Andric const unsigned Index = getResourceStateIndex(ResourceID); 3450b57cec5SDimitry Andric ResourceState &Resource = *Resources[Index]; 3460b57cec5SDimitry Andric assert(Resource.isAResourceGroup() && !Resource.isReserved() && 347*8bcb0991SDimitry Andric "Unexpected resource state found!"); 3480b57cec5SDimitry Andric Resource.setReserved(); 3490b57cec5SDimitry Andric ReservedResourceGroups ^= 1ULL << Index; 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric void ResourceManager::releaseResource(uint64_t ResourceID) { 3530b57cec5SDimitry Andric const unsigned Index = getResourceStateIndex(ResourceID); 3540b57cec5SDimitry Andric ResourceState &Resource = *Resources[Index]; 3550b57cec5SDimitry Andric Resource.clearReserved(); 3560b57cec5SDimitry Andric if (Resource.isAResourceGroup()) 3570b57cec5SDimitry Andric ReservedResourceGroups ^= 1ULL << Index; 358*8bcb0991SDimitry Andric // Now it is safe to release dispatch/issue resources. 359*8bcb0991SDimitry Andric if (Resource.isADispatchHazard()) 360*8bcb0991SDimitry Andric ReservedBuffers ^= 1ULL << Index; 3610b57cec5SDimitry Andric } 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric } // namespace mca 3640b57cec5SDimitry Andric } // namespace llvm 365