1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00

[MCA] Store extra information about processor resources in the ResourceManager.

Method ResourceManager::use() is responsible for updating the internal state of
used processor resources, as well as notifying resource groups that contain used
resources.

Before this patch, method 'use()' didn't know how to quickly obtain the set of
groups that contain a particular resource unit. It had to discover groups by
perform a potentially slow search (done by iterating over the set of processor
resource descriptors).

With this patch, the relationship between resource units and groups is stored in
the ResourceManager. That means, method 'use()' no longer has to search for
groups. This gives an average speedup of ~4-5% on a release build.

This patch also adds extra code comments in ResourceManager.h to better describe
the resource mask layout, and how resouce indices are computed from resource
masks.

llvm-svn: 350387
This commit is contained in:
Andrea Di Biagio 2019-01-04 12:31:14 +00:00
parent 5698d0dddb
commit 3b8b6c1505
2 changed files with 86 additions and 16 deletions

View File

@ -139,7 +139,30 @@ class ResourceState {
/// An index to the MCProcResourceDesc entry in the processor model. /// An index to the MCProcResourceDesc entry in the processor model.
const unsigned ProcResourceDescIndex; const unsigned ProcResourceDescIndex;
/// A resource mask. This is generated by the tool with the help of /// A resource mask. This is generated by the tool with the help of
/// function `mca::createProcResourceMasks' (see Support.h). /// function `mca::computeProcResourceMasks' (see Support.h).
///
/// Field ResourceMask only has one bit set if this resource state describes a
/// processor resource unit (i.e. this is not a group). That means, we can
/// quickly check if a resource is a group by simply counting the number of
/// bits that are set in the mask.
///
/// The most significant bit of a mask (MSB) uniquely identifies a resource.
/// Remaining bits are used to describe the composition of a group (Group).
///
/// Example (little endian):
/// Resource | Mask | MSB | Group
/// ---------+------------+------------+------------
/// A | 0b000001 | 0b000001 | 0b000000
/// | | |
/// B | 0b000010 | 0b000010 | 0b000000
/// | | |
/// C | 0b010000 | 0b010000 | 0b000000
/// | | |
/// D | 0b110010 | 0b100000 | 0b010010
///
/// In this example, resources A, B and C are processor resource units.
/// Only resource D is a group resource, and it contains resources B and C.
/// That is because MSB(B) and MSB(C) are both contained within Group(D).
const uint64_t ResourceMask; const uint64_t ResourceMask;
/// A ProcResource can have multiple units. /// A ProcResource can have multiple units.
@ -279,10 +302,39 @@ typedef std::pair<unsigned, unsigned> BufferUsageEntry;
/// In future, it can be extended to support itineraries too through the same /// In future, it can be extended to support itineraries too through the same
/// public interface. /// public interface.
class ResourceManager { class ResourceManager {
// The resource manager owns all the ResourceState. // Set of resources available on the subtarget.
//
// There is an instance of ResourceState for every resource declared by the
// target scheduling model.
//
// Elements of this vector are ordered by resource kind. In particular,
// resource units take precedence over resource groups.
//
// The index of a processor resource in this vector depends on the value of
// its mask (see the description of field ResourceState::ResourceMask). In
// particular, it is computed as the position of the most significant bit set
// (MSB) in the mask plus one (since we want to ignore the invalid resource
// descriptor at index zero).
//
// Example (little endian):
//
// Resource | Mask | MSB | Index
// ---------+---------+---------+-------
// A | 0b00001 | 0b00001 | 1
// | | |
// B | 0b00100 | 0b00100 | 3
// | | |
// C | 0b10010 | 0b10000 | 5
//
//
// The same index is also used to address elements within vector `Strategies`
// and vector `Resource2Groups`.
std::vector<std::unique_ptr<ResourceState>> Resources; std::vector<std::unique_ptr<ResourceState>> Resources;
std::vector<std::unique_ptr<ResourceStrategy>> Strategies; std::vector<std::unique_ptr<ResourceStrategy>> Strategies;
// Used to quickly identify groups that own a particular resource unit.
std::vector<uint64_t> Resource2Groups;
// Keeps track of which resources are busy, and how many cycles are left // Keeps track of which resources are busy, and how many cycles are left
// before those become usable again. // before those become usable again.
SmallDenseMap<ResourceRef, unsigned> BusyResources; SmallDenseMap<ResourceRef, unsigned> BusyResources;

View File

@ -115,10 +115,11 @@ getStrategyFor(const ResourceState &RS) {
return std::unique_ptr<ResourceStrategy>(nullptr); return std::unique_ptr<ResourceStrategy>(nullptr);
} }
ResourceManager::ResourceManager(const MCSchedModel &SM) { ResourceManager::ResourceManager(const MCSchedModel &SM)
: Resources(SM.getNumProcResourceKinds()),
Strategies(SM.getNumProcResourceKinds()),
Resource2Groups(SM.getNumProcResourceKinds(), 0) {
computeProcResourceMasks(SM, ProcResID2Mask); computeProcResourceMasks(SM, ProcResID2Mask);
Resources.resize(SM.getNumProcResourceKinds());
Strategies.resize(SM.getNumProcResourceKinds());
for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) { for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
uint64_t Mask = ProcResID2Mask[I]; uint64_t Mask = ProcResID2Mask[I];
@ -127,6 +128,24 @@ ResourceManager::ResourceManager(const MCSchedModel &SM) {
llvm::make_unique<ResourceState>(*SM.getProcResource(I), I, Mask); llvm::make_unique<ResourceState>(*SM.getProcResource(I), I, Mask);
Strategies[Index] = getStrategyFor(*Resources[Index]); Strategies[Index] = getStrategyFor(*Resources[Index]);
} }
for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
uint64_t Mask = ProcResID2Mask[I];
unsigned Index = getResourceStateIndex(Mask);
const ResourceState &RS = *Resources[Index];
if (!RS.isAResourceGroup())
continue;
uint64_t GroupMaskIdx = 1ULL << (Index - 1);
Mask -= GroupMaskIdx;
while (Mask) {
// Extract lowest set isolated bit.
uint64_t Unit = Mask & (-Mask);
unsigned IndexUnit = getResourceStateIndex(Unit);
Resource2Groups[IndexUnit] |= GroupMaskIdx;
Mask ^= Unit;
}
}
} }
void ResourceManager::setCustomStrategyImpl(std::unique_ptr<ResourceStrategy> S, void ResourceManager::setCustomStrategyImpl(std::unique_ptr<ResourceStrategy> S,
@ -179,17 +198,16 @@ void ResourceManager::use(const ResourceRef &RR) {
if (RS.isReady()) if (RS.isReady())
return; return;
// Notify to other resources that RR.first is no longer available. // Notify groups that RR.first is no longer available.
for (std::unique_ptr<ResourceState> &Res : Resources) { uint64_t Users = Resource2Groups[RSID];
ResourceState &Current = *Res; while (Users) {
if (!Current.isAResourceGroup() || Current.getResourceMask() == RR.first) // Extract lowest set isolated bit.
continue; unsigned GroupIndex = getResourceStateIndex(Users & (-Users));
ResourceState &CurrentUser = *Resources[GroupIndex];
if (Current.containsResource(RR.first)) { CurrentUser.markSubResourceAsUsed(RR.first);
unsigned Index = getResourceStateIndex(Current.getResourceMask()); Strategies[GroupIndex]->used(RR.first);
Current.markSubResourceAsUsed(RR.first); // Reset lowest set bit.
Strategies[Index]->used(RR.first); Users &= Users - 1;
}
} }
} }