[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 4cebc9db04
commit 7bec693433
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.
const unsigned ProcResourceDescIndex;
/// 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;
/// 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
/// public interface.
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<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
// before those become usable again.
SmallDenseMap<ResourceRef, unsigned> BusyResources;

View File

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