Skip to content
Snippets Groups Projects
Commit 4704f038 authored by Andrea Di Biagio's avatar Andrea Di Biagio
Browse files

[llvm-mca] Move the routine that computes processor resource masks to its own file.

Function computeProcResourceMasks is used by the ResourceManager (owned by the
Scheduler) to compute resource masks for processor resources.  Before this
refactoring, there was an implicit dependency between the Scheduler and the
InstrBuilder. That is because InstrBuilder has to know about resource masks when
computing the set of processor resources consumed by a new instruction.

With this patch, the functionality that computes resource masks has been
extracted from the ResourceManager, and moved to a separate file (Support.h). 
This helps removing the dependency between the Scheduler and the InstrBuilder.

No functional change intended.

llvm-svn: 327973
parent a713ebea
No related branches found
No related tags found
No related merge requests found
......@@ -34,7 +34,7 @@ void Backend::runCycle(unsigned Cycle) {
while (SM.hasNext()) {
InstRef IR = SM.peekNext();
std::unique_ptr<Instruction> NewIS(
IB->createInstruction(STI, IR.first, *IR.second));
IB->createInstruction(IR.first, *IR.second));
const InstrDesc &Desc = NewIS->getDesc();
if (!DU->isAvailable(Desc.NumMicroOps) ||
!DU->canDispatch(IR.first, *NewIS))
......
......@@ -72,7 +72,7 @@ public:
this, MRI, Subtarget.getSchedModel().MicroOpBufferSize,
RegisterFileSize, MaxRetirePerCycle, DispatchWidth, HWS.get())),
SM(Source), Cycles(0) {
IB = llvm::make_unique<InstrBuilder>(MCII, HWS->getProcResourceMasks());
IB = llvm::make_unique<InstrBuilder>(Subtarget, MCII);
HWS->setDispatchUnit(DU.get());
}
......
......@@ -21,7 +21,8 @@ add_llvm_tool(llvm-mca
llvm-mca.cpp
ResourcePressureView.cpp
Scheduler.cpp
TimelineView.cpp
Support.cpp
SummaryView.cpp
TimelineView.cpp
View.cpp
)
......@@ -357,8 +357,7 @@ static void populateReads(InstrDesc &ID, const MCInst &MCI,
}
}
void InstrBuilder::createInstrDescImpl(const MCSubtargetInfo &STI,
const MCInst &MCI) {
void InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
assert(STI.getSchedModel().hasInstrSchedModel() &&
"Itineraries are not yet supported!");
......@@ -410,17 +409,15 @@ void InstrBuilder::createInstrDescImpl(const MCSubtargetInfo &STI,
Descriptors[Opcode] = std::unique_ptr<const InstrDesc>(ID);
}
const InstrDesc &InstrBuilder::getOrCreateInstrDesc(const MCSubtargetInfo &STI,
const MCInst &MCI) {
const InstrDesc &InstrBuilder::getOrCreateInstrDesc(const MCInst &MCI) {
auto it = Descriptors.find(MCI.getOpcode());
if (it == Descriptors.end())
createInstrDescImpl(STI, MCI);
createInstrDescImpl(MCI);
return *Descriptors[MCI.getOpcode()].get();
}
Instruction *InstrBuilder::createInstruction(const MCSubtargetInfo &STI,
unsigned Idx, const MCInst &MCI) {
const InstrDesc &D = getOrCreateInstrDesc(STI, MCI);
Instruction *InstrBuilder::createInstruction(unsigned Idx, const MCInst &MCI) {
const InstrDesc &D = getOrCreateInstrDesc(MCI);
Instruction *NewIS = new Instruction(D);
// Populate Reads first.
......@@ -446,7 +443,7 @@ Instruction *InstrBuilder::createInstruction(const MCSubtargetInfo &STI,
assert(RegID > 0 && "Invalid register ID found!");
ReadState *NewRDS = new ReadState(RD, RegID);
NewIS->getUses().emplace_back(std::unique_ptr<ReadState>(NewRDS));
}
}
// Now populate writes.
for (const WriteDescriptor &WD : D.Writes) {
......
......@@ -16,6 +16,7 @@
#define LLVM_TOOLS_LLVM_MCA_INSTRBUILDER_H
#include "Instruction.h"
#include "Support.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
......@@ -34,28 +35,26 @@ class DispatchUnit;
/// Information from the machine scheduling model is used to identify processor
/// resources that are consumed by an instruction.
class InstrBuilder {
const llvm::MCSubtargetInfo &STI;
const llvm::MCInstrInfo &MCII;
const llvm::ArrayRef<uint64_t> ProcResourceMasks;
llvm::SmallVector<uint64_t, 8> ProcResourceMasks;
llvm::DenseMap<unsigned short, std::unique_ptr<const InstrDesc>> Descriptors;
llvm::DenseMap<unsigned, std::unique_ptr<Instruction>> Instructions;
void createInstrDescImpl(const llvm::MCSubtargetInfo &STI,
const llvm::MCInst &MCI);
void createInstrDescImpl(const llvm::MCInst &MCI);
public:
InstrBuilder(const llvm::MCInstrInfo &mcii,
const llvm::ArrayRef<uint64_t> Masks)
: MCII(mcii), ProcResourceMasks(Masks) {}
InstrBuilder(const llvm::MCSubtargetInfo &sti, const llvm::MCInstrInfo &mcii)
: STI(sti), MCII(mcii),
ProcResourceMasks(STI.getSchedModel().getNumProcResourceKinds()) {
computeProcResourceMasks(STI.getSchedModel(), ProcResourceMasks);
}
const InstrDesc &getOrCreateInstrDesc(const llvm::MCSubtargetInfo &STI,
const llvm::MCInst &MCI);
const InstrDesc &getOrCreateInstrDesc(const llvm::MCInst &MCI);
Instruction *createInstruction(const llvm::MCSubtargetInfo &STI,
unsigned Idx,
const llvm::MCInst &MCI);
Instruction *createInstruction(unsigned Idx, const llvm::MCInst &MCI);
};
} // namespace mca
#endif
......@@ -11,9 +11,10 @@
//
//===----------------------------------------------------------------------===//
#include "Scheduler.h"
#include "Backend.h"
#include "HWEventListener.h"
#include "Scheduler.h"
#include "Support.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
......@@ -43,6 +44,12 @@ void ResourceState::dump() const {
}
#endif
void ResourceManager::initialize(const llvm::MCSchedModel &SM) {
computeProcResourceMasks(SM, ProcResID2Mask);
for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I)
addResource(*SM.getProcResource(I), I, ProcResID2Mask[I]);
}
// Adds a new resource state in Resources, as well as a new descriptor in
// ResourceDescriptor. Map 'Resources' allows to quickly obtain ResourceState
// objects from resource mask identifiers.
......@@ -52,36 +59,6 @@ void ResourceManager::addResource(const MCProcResourceDesc &Desc,
Resources[Mask] = llvm::make_unique<ResourceState>(Desc, Index, Mask);
}
// Populate vector ProcResID2Mask with resource masks. One per each processor
// resource declared by the scheduling model.
void ResourceManager::computeProcResourceMasks(const MCSchedModel &SM) {
unsigned ProcResourceID = 0;
// Create a unique bitmask for every processor resource unit.
// Skip resource at index 0, since it always references 'InvalidUnit'.
ProcResID2Mask.resize(SM.getNumProcResourceKinds());
for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) {
const MCProcResourceDesc &Desc = *SM.getProcResource(I);
if (Desc.SubUnitsIdxBegin)
continue;
ProcResID2Mask[I] = 1ULL << ProcResourceID;
ProcResourceID++;
}
// Create a unique bitmask for every processor resource group.
for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) {
const MCProcResourceDesc &Desc = *SM.getProcResource(I);
if (!Desc.SubUnitsIdxBegin)
continue;
ProcResID2Mask[I] |= 1ULL << ProcResourceID;
for (unsigned U = 0; U < Desc.NumUnits; ++U) {
uint64_t OtherMask = ProcResID2Mask[Desc.SubUnitsIdxBegin[U]];
ProcResID2Mask[I] |= OtherMask;
}
ProcResourceID++;
}
}
// Returns the actual resource consumed by this Use.
// First, is the primary resource ID.
// Second, is the specific sub-resource ID.
......
......@@ -60,22 +60,8 @@ enum ResourceStateEvent {
class ResourceState {
// Index to the MCProcResourceDesc in the processor Model.
unsigned ProcResourceDescIndex;
// A resource unique identifier generated by the tool.
// For processor resource groups, the number of number of bits set in this
// mask is equivalent to the cardinality of the group plus one.
// Excluding the most significant bit, the remaining bits in the resource mask
// identify resources that are part of the group.
//
// Example, lets assume that this ResourceState describes a
// group containing ResourceA and ResourceB:
//
// ResourceA -- Mask: 0b001
// ResourceB -- Mask: 0b010
// ResourceAB -- Mask: 0b100 U (ResourceA::Mask | ResourceB::Mask) == 0b111
//
// There is only one bit set for non-group resources.
// A ResourceMask can be used to solve set membership problems with simple bit
// manipulation operations.
// A resource mask. This is generated by the tool with the help of
// function `mca::createProcResourceMasks' (see Support.h).
uint64_t ResourceMask;
// A ProcResource can specify a number of units. For the purpose of dynamic
......@@ -309,16 +295,8 @@ class ResourceManager {
void addResource(const llvm::MCProcResourceDesc &Desc, unsigned Index,
uint64_t Mask);
// Compute processor resource masks for each processor resource declared by
// the scheduling model.
void computeProcResourceMasks(const llvm::MCSchedModel &SM);
// Populate resource descriptors.
void initialize(const llvm::MCSchedModel &SM) {
computeProcResourceMasks(SM);
for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I)
addResource(*SM.getProcResource(I), I, ProcResID2Mask[I]);
}
void initialize(const llvm::MCSchedModel &SM);
// Returns the actual resource unit that will be used.
ResourceRef selectPipe(uint64_t ResourceID);
......@@ -354,7 +332,10 @@ class ResourceManager {
}
public:
ResourceManager(const llvm::MCSchedModel &SM) { initialize(SM); }
ResourceManager(const llvm::MCSchedModel &SM)
: ProcResID2Mask(SM.getNumProcResourceKinds()) {
initialize(SM);
}
// Returns RS_BUFFER_AVAILABLE if buffered resources are not reserved, and if
// there are enough available slots in the buffers.
......@@ -400,10 +381,6 @@ public:
}
}
const llvm::ArrayRef<uint64_t> getProcResMasks() const {
return ProcResID2Mask;
}
#ifndef NDEBUG
void dump() const {
for (const std::pair<uint64_t, UniqueResourceState> &Resource : Resources)
......@@ -525,10 +502,6 @@ public:
Resources->getBuffersUsage(Usage);
}
const llvm::ArrayRef<uint64_t> getProcResourceMasks() const {
return Resources->getProcResMasks();
}
#ifndef NDEBUG
void dump() const;
#endif
......
//===--------------------- Support.cpp ----------------------------*- C++
//-*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This file implements a few helper functions used by various backend
/// components.
///
//===----------------------------------------------------------------------===//
#include "Support.h"
#include "llvm/MC/MCSchedule.h"
namespace mca {
using namespace llvm;
void computeProcResourceMasks(const MCSchedModel &SM,
SmallVectorImpl<uint64_t> &Masks) {
unsigned ProcResourceID = 0;
// Create a unique bitmask for every processor resource unit.
// Skip resource at index 0, since it always references 'InvalidUnit'.
Masks.resize(SM.getNumProcResourceKinds());
for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) {
const MCProcResourceDesc &Desc = *SM.getProcResource(I);
if (Desc.SubUnitsIdxBegin)
continue;
Masks[I] = 1ULL << ProcResourceID;
ProcResourceID++;
}
// Create a unique bitmask for every processor resource group.
for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) {
const MCProcResourceDesc &Desc = *SM.getProcResource(I);
if (!Desc.SubUnitsIdxBegin)
continue;
Masks[I] = 1ULL << ProcResourceID;
for (unsigned U = 0; U < Desc.NumUnits; ++U) {
uint64_t OtherMask = Masks[Desc.SubUnitsIdxBegin[U]];
Masks[I] |= OtherMask;
}
ProcResourceID++;
}
}
} // namespace mca
//===--------------------- Support.h ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// Helper functions used by various backend components.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_MCA_SUPPORT_H
#define LLVM_TOOLS_LLVM_MCA_SUPPORT_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCSchedule.h"
namespace mca {
/// Populates vector Masks with processor resource masks.
///
/// The number of bits set in a mask depends on the processor resource type.
/// Each processor resource mask has at least one bit set. For groups, the
/// number of bits set in the mask is equal to the cardinality of the group plus
/// one. Excluding the most significant bit, the remaining bits in the mask
/// identify processor resources that are part of the group.
///
/// Example:
///
/// ResourceA -- Mask: 0b001
/// ResourceB -- Mask: 0b010
/// ResourceAB -- Mask: 0b100 U (ResourceA::Mask | ResourceB::Mask) == 0b111
///
/// ResourceAB is a processor resource group containing ResourceA and ResourceB.
/// Each resource mask uniquely identifies a resource; both ResourceA and
/// ResourceB only have one bit set.
/// ResourceAB is a group; excluding the most significant bit in the mask, the
/// remaining bits identify the composition of the group.
///
/// Resource masks are used by the ResourceManager to solve set membership
/// problems with simple bit manipulation operations.
void computeProcResourceMasks(const llvm::MCSchedModel &SM,
llvm::SmallVectorImpl<uint64_t> &Masks);
} // namespace mca
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment