aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib
diff options
context:
space:
mode:
authorAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>2019-08-15 12:39:55 +0000
committerAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>2019-08-15 12:39:55 +0000
commit7aa0dbb664ea05e233c503c009052f8682fc0f62 (patch)
tree4242a7b51593f17dd1508be6484ed2c4f83d0991 /llvm/lib
parentfd72bf21c958ae2fdfaa8654df55367c72575d3a (diff)
downloadllvm-7aa0dbb664ea05e233c503c009052f8682fc0f62.zip
llvm-7aa0dbb664ea05e233c503c009052f8682fc0f62.tar.gz
llvm-7aa0dbb664ea05e233c503c009052f8682fc0f62.tar.bz2
[MCA] Slightly refactor the logic in ResourceManager. NFCI
This patch slightly changes the API in the attempt to simplify resource buffer queries. It is done in preparation for a patch that will enable support for macro fusion. llvm-svn: 368994
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/MCA/HardwareUnits/ResourceManager.cpp55
-rw-r--r--llvm/lib/MCA/HardwareUnits/Scheduler.cpp6
-rw-r--r--llvm/lib/MCA/InstrBuilder.cpp30
-rw-r--r--llvm/lib/MCA/Stages/ExecuteStage.cpp14
4 files changed, 57 insertions, 48 deletions
diff --git a/llvm/lib/MCA/HardwareUnits/ResourceManager.cpp b/llvm/lib/MCA/HardwareUnits/ResourceManager.cpp
index 06f2476..5c91198 100644
--- a/llvm/lib/MCA/HardwareUnits/ResourceManager.cpp
+++ b/llvm/lib/MCA/HardwareUnits/ResourceManager.cpp
@@ -114,7 +114,8 @@ ResourceManager::ResourceManager(const MCSchedModel &SM)
Resource2Groups(SM.getNumProcResourceKinds() - 1, 0),
ProcResID2Mask(SM.getNumProcResourceKinds(), 0),
ResIndex2ProcResID(SM.getNumProcResourceKinds() - 1, 0),
- ProcResUnitMask(0), ReservedResourceGroups(0) {
+ ProcResUnitMask(0), ReservedResourceGroups(0),
+ AvailableBuffers(~0ULL), ReservedBuffers(0) {
computeProcResourceMasks(SM, ProcResID2Mask);
// initialize vector ResIndex2ProcResID.
@@ -241,33 +242,41 @@ void ResourceManager::release(const ResourceRef &RR) {
}
ResourceStateEvent
-ResourceManager::canBeDispatched(ArrayRef<uint64_t> Buffers) const {
- ResourceStateEvent Result = ResourceStateEvent::RS_BUFFER_AVAILABLE;
- for (uint64_t Buffer : Buffers) {
- ResourceState &RS = *Resources[getResourceStateIndex(Buffer)];
- Result = RS.isBufferAvailable();
- if (Result != ResourceStateEvent::RS_BUFFER_AVAILABLE)
- break;
- }
- return Result;
+ResourceManager::canBeDispatched(uint64_t ConsumedBuffers) const {
+ if (ConsumedBuffers & ReservedBuffers)
+ return ResourceStateEvent::RS_RESERVED;
+ if (ConsumedBuffers & (~AvailableBuffers))
+ return ResourceStateEvent::RS_BUFFER_UNAVAILABLE;
+ return ResourceStateEvent::RS_BUFFER_AVAILABLE;
}
-void ResourceManager::reserveBuffers(ArrayRef<uint64_t> Buffers) {
- for (const uint64_t Buffer : Buffers) {
- ResourceState &RS = *Resources[getResourceStateIndex(Buffer)];
+void ResourceManager::reserveBuffers(uint64_t ConsumedBuffers) {
+ while (ConsumedBuffers) {
+ uint64_t CurrentBuffer = ConsumedBuffers & (-ConsumedBuffers);
+ ResourceState &RS = *Resources[getResourceStateIndex(CurrentBuffer)];
+ ConsumedBuffers ^= CurrentBuffer;
assert(RS.isBufferAvailable() == ResourceStateEvent::RS_BUFFER_AVAILABLE);
- RS.reserveBuffer();
-
+ if (!RS.reserveBuffer())
+ AvailableBuffers ^= CurrentBuffer;
if (RS.isADispatchHazard()) {
- assert(!RS.isReserved());
- RS.setReserved();
+ // Reserve this buffer now, and release it once pipeline resources
+ // consumed by the instruction become available again.
+ // We do this to simulate an in-order dispatch/issue of instructions.
+ ReservedBuffers ^= CurrentBuffer;
}
}
}
-void ResourceManager::releaseBuffers(ArrayRef<uint64_t> Buffers) {
- for (const uint64_t R : Buffers)
- Resources[getResourceStateIndex(R)]->releaseBuffer();
+void ResourceManager::releaseBuffers(uint64_t ConsumedBuffers) {
+ AvailableBuffers |= ConsumedBuffers;
+ while (ConsumedBuffers) {
+ uint64_t CurrentBuffer = ConsumedBuffers & (-ConsumedBuffers);
+ ResourceState &RS = *Resources[getResourceStateIndex(CurrentBuffer)];
+ ConsumedBuffers ^= CurrentBuffer;
+ RS.releaseBuffer();
+ // Do not unreserve dispatch hazard resource buffers. Wait until all
+ // pipeline resources have been freed too.
+ }
}
uint64_t ResourceManager::checkAvailability(const InstrDesc &Desc) const {
@@ -322,7 +331,6 @@ void ResourceManager::cycleEvent(SmallVectorImpl<ResourceRef> &ResourcesFreed) {
if (countPopulation(RR.first) == 1)
release(RR);
-
releaseResource(RR.first);
ResourcesFreed.push_back(RR);
}
@@ -336,7 +344,7 @@ void ResourceManager::reserveResource(uint64_t ResourceID) {
const unsigned Index = getResourceStateIndex(ResourceID);
ResourceState &Resource = *Resources[Index];
assert(Resource.isAResourceGroup() && !Resource.isReserved() &&
- "Unexpected resource found!");
+ "Unexpected resource state found!");
Resource.setReserved();
ReservedResourceGroups ^= 1ULL << Index;
}
@@ -347,6 +355,9 @@ void ResourceManager::releaseResource(uint64_t ResourceID) {
Resource.clearReserved();
if (Resource.isAResourceGroup())
ReservedResourceGroups ^= 1ULL << Index;
+ // Now it is safe to release dispatch/issue resources.
+ if (Resource.isADispatchHazard())
+ ReservedBuffers ^= 1ULL << Index;
}
} // namespace mca
diff --git a/llvm/lib/MCA/HardwareUnits/Scheduler.cpp b/llvm/lib/MCA/HardwareUnits/Scheduler.cpp
index 0f0f2ff..2d6b22c 100644
--- a/llvm/lib/MCA/HardwareUnits/Scheduler.cpp
+++ b/llvm/lib/MCA/HardwareUnits/Scheduler.cpp
@@ -40,7 +40,7 @@ void Scheduler::dump() const {
Scheduler::Status Scheduler::isAvailable(const InstRef &IR) {
const InstrDesc &Desc = IR.getInstruction()->getDesc();
- ResourceStateEvent RSE = Resources->canBeDispatched(Desc.Buffers);
+ ResourceStateEvent RSE = Resources->canBeDispatched(Desc.UsedBuffers);
HadTokenStall = RSE != RS_BUFFER_AVAILABLE;
switch (RSE) {
@@ -106,7 +106,7 @@ void Scheduler::issueInstruction(
bool HasDependentUsers = Inst.hasDependentUsers();
HasDependentUsers |= Inst.isMemOp() && LSU.hasDependentUsers(IR);
- Resources->releaseBuffers(Inst.getDesc().Buffers);
+ Resources->releaseBuffers(Inst.getDesc().UsedBuffers);
issueInstructionImpl(IR, UsedResources);
// Instructions that have been issued during this cycle might have unblocked
// other dependent instructions. Dependent instructions may be issued during
@@ -301,7 +301,7 @@ bool Scheduler::mustIssueImmediately(const InstRef &IR) const {
bool Scheduler::dispatch(InstRef &IR) {
Instruction &IS = *IR.getInstruction();
const InstrDesc &Desc = IS.getDesc();
- Resources->reserveBuffers(Desc.Buffers);
+ Resources->reserveBuffers(Desc.UsedBuffers);
// If necessary, reserve queue entries in the load-store unit (LSU).
if (IS.isMemOp())
diff --git a/llvm/lib/MCA/InstrBuilder.cpp b/llvm/lib/MCA/InstrBuilder.cpp
index 8299203..ee9e2bcd 100644
--- a/llvm/lib/MCA/InstrBuilder.cpp
+++ b/llvm/lib/MCA/InstrBuilder.cpp
@@ -80,7 +80,7 @@ static void initializeUsedResources(InstrDesc &ID,
if (PR.BufferSize < 0) {
AllInOrderResources = false;
} else {
- Buffers.setBit(PRE->ProcResourceIdx);
+ Buffers.setBit(getResourceStateIndex(Mask));
AnyDispatchHazards |= (PR.BufferSize == 0);
AllInOrderResources &= (PR.BufferSize <= 1);
}
@@ -139,9 +139,6 @@ 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):
//
@@ -177,20 +174,13 @@ static void initializeUsedResources(InstrDesc &ID,
uint64_t Mask = ProcResourceMasks[I];
if (Mask != SR.first && ((Mask & SR.first) == SR.first))
- Buffers.setBit(I);
+ Buffers.setBit(getResourceStateIndex(Mask));
}
}
- // Now set the buffers.
- if (unsigned NumBuffers = Buffers.countPopulation()) {
- ID.Buffers.resize(NumBuffers);
- for (unsigned I = 0, E = NumProcResources; I < E && NumBuffers; ++I) {
- if (Buffers[I]) {
- --NumBuffers;
- ID.Buffers[NumBuffers] = ProcResourceMasks[I];
- }
- }
- }
+ ID.UsedBuffers = Buffers.getZExtValue();
+ ID.UsedProcResUnits = UsedResourceUnits;
+ ID.UsedProcResGroups = UsedResourceGroups;
LLVM_DEBUG({
for (const std::pair<uint64_t, ResourceUsage> &R : ID.Resources)
@@ -198,8 +188,12 @@ static void initializeUsedResources(InstrDesc &ID,
<< "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';
+ uint64_t BufferIDs = ID.UsedBuffers;
+ while (BufferIDs) {
+ uint64_t Current = BufferIDs & (-BufferIDs);
+ dbgs() << "\t\tBuffer Mask=" << format_hex(Current, 16) << '\n';
+ BufferIDs ^= Current;
+ }
dbgs() << "\t\t Used Units=" << format_hex(ID.UsedProcResUnits, 16) << '\n';
dbgs() << "\t\tUsed Groups=" << format_hex(ID.UsedProcResGroups, 16)
<< '\n';
@@ -493,7 +487,7 @@ Error InstrBuilder::verifyInstrDesc(const InstrDesc &ID,
return ErrorSuccess();
bool UsesMemory = ID.MayLoad || ID.MayStore;
- bool UsesBuffers = !ID.Buffers.empty();
+ bool UsesBuffers = ID.UsedBuffers;
bool UsesResources = !ID.Resources.empty();
if (!UsesMemory && !UsesBuffers && !UsesResources)
return ErrorSuccess();
diff --git a/llvm/lib/MCA/Stages/ExecuteStage.cpp b/llvm/lib/MCA/Stages/ExecuteStage.cpp
index a2b361f..9166f07 100644
--- a/llvm/lib/MCA/Stages/ExecuteStage.cpp
+++ b/llvm/lib/MCA/Stages/ExecuteStage.cpp
@@ -269,13 +269,17 @@ void ExecuteStage::notifyInstructionIssued(
void ExecuteStage::notifyReservedOrReleasedBuffers(const InstRef &IR,
bool Reserved) const {
- const InstrDesc &Desc = IR.getInstruction()->getDesc();
- if (Desc.Buffers.empty())
+ uint64_t UsedBuffers = IR.getInstruction()->getDesc().UsedBuffers;
+ if (!UsedBuffers)
return;
- SmallVector<unsigned, 4> BufferIDs(Desc.Buffers.begin(), Desc.Buffers.end());
- std::transform(Desc.Buffers.begin(), Desc.Buffers.end(), BufferIDs.begin(),
- [&](uint64_t Op) { return HWS.getResourceID(Op); });
+ SmallVector<unsigned, 4> BufferIDs(countPopulation(UsedBuffers), 0);
+ for (unsigned I = 0, E = BufferIDs.size(); I < E; ++I) {
+ uint64_t CurrentBufferMask = UsedBuffers & (-UsedBuffers);
+ BufferIDs[I] = HWS.getResourceID(CurrentBufferMask);
+ UsedBuffers ^= CurrentBufferMask;
+ }
+
if (Reserved) {
for (HWEventListener *Listener : getListeners())
Listener->onReservedBuffers(IR, BufferIDs);