[llvm] r340176 - [llvm-mca] Make the LSUnit a HardwareUnit, and allow derived classes to implement a different memory consistency model.
Andrea Di Biagio via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 20 07:41:36 PDT 2018
Author: adibiagio
Date: Mon Aug 20 07:41:36 2018
New Revision: 340176
URL: http://llvm.org/viewvc/llvm-project?rev=340176&view=rev
Log:
[llvm-mca] Make the LSUnit a HardwareUnit, and allow derived classes to implement a different memory consistency model.
The LSUnit is now a HardwareUnit, and it is owned by the mca::Context.
Derived classes can now implement a different consistency model by overriding
method `LSUnit::isReady()`.
This patch also slightly refactors the Scheduler interface in the attempt to
simplifying the interaction between ExecuteStage and the underlying Scheduler.
Modified:
llvm/trunk/tools/llvm-mca/Context.cpp
llvm/trunk/tools/llvm-mca/ExecuteStage.cpp
llvm/trunk/tools/llvm-mca/LSUnit.cpp
llvm/trunk/tools/llvm-mca/LSUnit.h
llvm/trunk/tools/llvm-mca/Scheduler.cpp
llvm/trunk/tools/llvm-mca/Scheduler.h
Modified: llvm/trunk/tools/llvm-mca/Context.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/Context.cpp?rev=340176&r1=340175&r2=340176&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/Context.cpp (original)
+++ llvm/trunk/tools/llvm-mca/Context.cpp Mon Aug 20 07:41:36 2018
@@ -36,8 +36,9 @@ Context::createDefaultPipeline(const Pip
// Create the hardware units defining the backend.
auto RCU = llvm::make_unique<RetireControlUnit>(SM);
auto PRF = llvm::make_unique<RegisterFile>(SM, MRI, Opts.RegisterFileSize);
- auto HWS = llvm::make_unique<Scheduler>(
- SM, Opts.LoadQueueSize, Opts.StoreQueueSize, Opts.AssumeNoAlias);
+ auto LSU = llvm::make_unique<LSUnit>(Opts.LoadQueueSize, Opts.StoreQueueSize,
+ Opts.AssumeNoAlias);
+ auto HWS = llvm::make_unique<Scheduler>(SM, LSU.get());
// Create the pipeline and its stages.
auto StagePipeline = llvm::make_unique<Pipeline>();
@@ -47,9 +48,10 @@ Context::createDefaultPipeline(const Pip
auto Execute = llvm::make_unique<ExecuteStage>(*HWS);
auto Retire = llvm::make_unique<RetireStage>(*RCU, *PRF);
- // Add the hardware to the context.
+ // Pass the ownership of all the hardware units to this Context.
addHardwareUnit(std::move(RCU));
addHardwareUnit(std::move(PRF));
+ addHardwareUnit(std::move(LSU));
addHardwareUnit(std::move(HWS));
// Build the pipeline.
Modified: llvm/trunk/tools/llvm-mca/ExecuteStage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/ExecuteStage.cpp?rev=340176&r1=340175&r2=340176&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/ExecuteStage.cpp (original)
+++ llvm/trunk/tools/llvm-mca/ExecuteStage.cpp Mon Aug 20 07:41:36 2018
@@ -25,17 +25,17 @@ namespace mca {
using namespace llvm;
-HWStallEvent::GenericEventType toHWStallEventType(Scheduler::StallKind Event) {
- switch (Event) {
- case Scheduler::LoadQueueFull:
+HWStallEvent::GenericEventType toHWStallEventType(Scheduler::Status Status) {
+ switch (Status) {
+ case Scheduler::SC_LOAD_QUEUE_FULL:
return HWStallEvent::LoadQueueFull;
- case Scheduler::StoreQueueFull:
+ case Scheduler::SC_STORE_QUEUE_FULL:
return HWStallEvent::StoreQueueFull;
- case Scheduler::SchedulerQueueFull:
+ case Scheduler::SC_BUFFERS_FULL:
return HWStallEvent::SchedulerQueueFull;
- case Scheduler::DispatchGroupStall:
+ case Scheduler::SC_DISPATCH_GROUP_STALL:
return HWStallEvent::DispatchGroupStall;
- case Scheduler::NoStall:
+ case Scheduler::SC_AVAILABLE:
return HWStallEvent::Invalid;
}
@@ -43,15 +43,15 @@ HWStallEvent::GenericEventType toHWStall
}
bool ExecuteStage::isAvailable(const InstRef &IR) const {
- Scheduler::StallKind Event = Scheduler::NoStall;
- if (HWS.canBeDispatched(IR, Event))
- return true;
- HWStallEvent::GenericEventType ET = toHWStallEventType(Event);
- notifyEvent<HWStallEvent>(HWStallEvent(ET, IR));
- return false;
+ if (Scheduler::Status S = HWS.isAvailable(IR)) {
+ HWStallEvent::GenericEventType ET = toHWStallEventType(S);
+ notifyEvent<HWStallEvent>(HWStallEvent(ET, IR));
+ return false;
+ }
+
+ return true;
}
-// Reclaim the simulated resources used by the scheduler.
void ExecuteStage::reclaimSchedulerResources() {
SmallVector<ResourceRef, 8> ResourcesFreed;
HWS.reclaimSimulatedResources(ResourcesFreed);
@@ -59,7 +59,6 @@ void ExecuteStage::reclaimSchedulerResou
notifyResourceAvailable(RR);
}
-// Update the scheduler's instruction queues.
Error ExecuteStage::updateSchedulerQueues() {
SmallVector<InstRef, 4> InstructionIDs;
HWS.updateIssuedSet(InstructionIDs);
@@ -77,7 +76,6 @@ Error ExecuteStage::updateSchedulerQueue
return ErrorSuccess();
}
-// Issue instructions that are waiting in the scheduler's ready queue.
Error ExecuteStage::issueReadyInstructions() {
SmallVector<InstRef, 4> InstructionIDs;
InstRef IR = HWS.select();
@@ -145,39 +143,20 @@ Error ExecuteStage::execute(InstRef &IR)
// be released after MCIS is issued, and all the ResourceCycles for those
// units have been consumed.
const InstrDesc &Desc = IR.getInstruction()->getDesc();
- HWS.reserveBuffers(Desc.Buffers);
+ HWS.dispatch(IR);
notifyReservedBuffers(Desc.Buffers);
-
- // Obtain a slot in the LSU. If we cannot reserve resources, return true, so
- // that succeeding stages can make progress.
- if (!HWS.reserveResources(IR))
+ if (!HWS.isReady(IR))
return ErrorSuccess();
// If we did not return early, then the scheduler is ready for execution.
notifyInstructionReady(IR);
- // Don't add a zero-latency instruction to the Wait or Ready queue.
- // A zero-latency instruction doesn't consume any scheduler resources. That is
- // because it doesn't need to be executed, and it is often removed at register
- // renaming stage. For example, register-register moves are often optimized at
- // register renaming stage by simply updating register aliases. On some
- // targets, zero-idiom instructions (for example: a xor that clears the value
- // of a register) are treated specially, and are often eliminated at register
- // renaming stage.
- //
- // Instructions that use an in-order dispatch/issue processor resource must be
- // issued immediately to the pipeline(s). Any other in-order buffered
- // resources (i.e. BufferSize=1) is consumed.
- //
// If we cannot issue immediately, the HWS will add IR to its ready queue for
// execution later, so we must return early here.
- if (!HWS.issueImmediately(IR))
+ if (!HWS.mustIssueImmediately(IR))
return ErrorSuccess();
- LLVM_DEBUG(dbgs() << "[SCHEDULER] Instruction #" << IR
- << " issued immediately\n");
-
- // Issue IR. The resources for this issuance will be placed in 'Used.'
+ // Issue IR to the underlying pipelines.
SmallVector<std::pair<ResourceRef, double>, 4> Used;
HWS.issueInstruction(IR, Used);
@@ -193,7 +172,6 @@ Error ExecuteStage::execute(InstRef &IR)
}
void ExecuteStage::notifyInstructionExecuted(const InstRef &IR) {
- HWS.onInstructionExecuted(IR);
LLVM_DEBUG(dbgs() << "[E] Instruction Executed: #" << IR << '\n');
notifyEvent<HWInstructionEvent>(
HWInstructionEvent(HWInstructionEvent::Executed, IR));
Modified: llvm/trunk/tools/llvm-mca/LSUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/LSUnit.cpp?rev=340176&r1=340175&r2=340176&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/LSUnit.cpp (original)
+++ llvm/trunk/tools/llvm-mca/LSUnit.cpp Mon Aug 20 07:41:36 2018
@@ -51,33 +51,42 @@ void LSUnit::assignSQSlot(unsigned Index
StoreQueue.insert(Index);
}
-bool LSUnit::reserve(const InstRef &IR) {
+void LSUnit::dispatch(const InstRef &IR) {
const InstrDesc &Desc = IR.getInstruction()->getDesc();
- unsigned MayLoad = Desc.MayLoad;
- unsigned MayStore = Desc.MayStore;
unsigned IsMemBarrier = Desc.HasSideEffects;
- if (!MayLoad && !MayStore)
- return false;
+ assert((Desc.MayLoad || Desc.MayStore) && "Not a memory operation!");
const unsigned Index = IR.getSourceIndex();
- if (MayLoad) {
+ if (Desc.MayLoad) {
if (IsMemBarrier)
LoadBarriers.insert(Index);
assignLQSlot(Index);
}
- if (MayStore) {
+
+ if (Desc.MayStore) {
if (IsMemBarrier)
StoreBarriers.insert(Index);
assignSQSlot(Index);
}
- return true;
+}
+
+LSUnit::Status LSUnit::isAvailable(const InstRef &IR) const {
+ const InstrDesc &Desc = IR.getInstruction()->getDesc();
+ if (Desc.MayLoad && isLQFull())
+ return LSUnit::LSU_LQUEUE_FULL;
+ if (Desc.MayStore && isSQFull())
+ return LSUnit::LSU_SQUEUE_FULL;
+ return LSUnit::LSU_AVAILABLE;
}
bool LSUnit::isReady(const InstRef &IR) const {
+ const InstrDesc &Desc = IR.getInstruction()->getDesc();
const unsigned Index = IR.getSourceIndex();
- bool IsALoad = LoadQueue.count(Index) != 0;
- bool IsAStore = StoreQueue.count(Index) != 0;
- assert((IsALoad || IsAStore) && "Instruction is not in queue!");
+ bool IsALoad = Desc.MayLoad;
+ bool IsAStore = Desc.MayStore;
+ assert((IsALoad || IsAStore) && "Not a memory operation!");
+ assert((!IsALoad || LoadQueue.count(Index) == 1) && "Load not in queue!");
+ assert((!IsAStore || StoreQueue.count(Index) == 1) && "Store not in queue!");
if (IsALoad && !LoadBarriers.empty()) {
unsigned LoadBarrierIndex = *LoadBarriers.begin();
Modified: llvm/trunk/tools/llvm-mca/LSUnit.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/LSUnit.h?rev=340176&r1=340175&r2=340176&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/LSUnit.h (original)
+++ llvm/trunk/tools/llvm-mca/LSUnit.h Mon Aug 20 07:41:36 2018
@@ -16,6 +16,7 @@
#ifndef LLVM_TOOLS_LLVM_MCA_LSUNIT_H
#define LLVM_TOOLS_LLVM_MCA_LSUNIT_H
+#include "HardwareUnit.h"
#include <set>
namespace mca {
@@ -86,7 +87,7 @@ struct InstrDesc;
/// A load/store barrier is "executed" when it becomes the oldest entry in
/// the load/store queue(s). That also means, all the older loads/stores have
/// already been executed.
-class LSUnit {
+class LSUnit : public HardwareUnit {
// Load queue size.
// LQ_Size == 0 means that there are infinite slots in the load queue.
unsigned LQ_Size;
@@ -115,6 +116,11 @@ class LSUnit {
// before newer loads are issued.
std::set<unsigned> LoadBarriers;
+ bool isSQEmpty() const { return StoreQueue.empty(); }
+ bool isLQEmpty() const { return LoadQueue.empty(); }
+ bool isSQFull() const { return SQ_Size != 0 && StoreQueue.size() == SQ_Size; }
+ bool isLQFull() const { return LQ_Size != 0 && LoadQueue.size() == LQ_Size; }
+
public:
LSUnit(unsigned LQ = 0, unsigned SQ = 0, bool AssumeNoAlias = false)
: LQ_Size(LQ), SQ_Size(SQ), NoAlias(AssumeNoAlias) {}
@@ -123,22 +129,30 @@ public:
void dump() const;
#endif
- bool isSQEmpty() const { return StoreQueue.empty(); }
- bool isLQEmpty() const { return LoadQueue.empty(); }
- bool isSQFull() const { return SQ_Size != 0 && StoreQueue.size() == SQ_Size; }
- bool isLQFull() const { return LQ_Size != 0 && LoadQueue.size() == LQ_Size; }
-
- // Returns true if this instruction has been successfully enqueued.
- bool reserve(const InstRef &IR);
+ enum Status {
+ LSU_AVAILABLE = 0,
+ LSU_LQUEUE_FULL,
+ LSU_SQUEUE_FULL
+ };
+
+ // Returns LSU_AVAILABLE if there are enough load/store queue entries to serve
+ // IR. It also returns LSU_AVAILABLE if IR is not a memory operation.
+ Status isAvailable(const InstRef &IR) const;
+
+ // Allocates load/store queue resources for IR.
+ //
+ // This method assumes that a previous call to `isAvailable(IR)` returned
+ // LSU_AVAILABLE, and that IR is a memory operation.
+ void dispatch(const InstRef &IR);
- // The rules are:
+ // By default, rules are:
// 1. A store may not pass a previous store.
// 2. A load may not pass a previous store unless flag 'NoAlias' is set.
// 3. A load may pass a previous load.
// 4. A store may not pass a previous load (regardless of flag 'NoAlias').
// 5. A load has to wait until an older load barrier is fully executed.
// 6. A store has to wait until an older store barrier is fully executed.
- bool isReady(const InstRef &IR) const;
+ virtual bool isReady(const InstRef &IR) const;
void onInstructionExecuted(const InstRef &IR);
};
Modified: llvm/trunk/tools/llvm-mca/Scheduler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/Scheduler.cpp?rev=340176&r1=340175&r2=340176&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/Scheduler.cpp (original)
+++ llvm/trunk/tools/llvm-mca/Scheduler.cpp Mon Aug 20 07:41:36 2018
@@ -171,7 +171,7 @@ bool ResourceManager::canBeIssued(const
// Returns true if all resources are in-order, and there is at least one
// resource which is a dispatch hazard (BufferSize = 0).
-bool ResourceManager::mustIssueImmediately(const InstrDesc &Desc) {
+bool ResourceManager::mustIssueImmediately(const InstrDesc &Desc) const {
if (!canBeIssued(Desc))
return false;
bool AllInOrderResources = all_of(Desc.Buffers, [&](uint64_t BufferMask) {
@@ -257,29 +257,29 @@ void Scheduler::dump() const {
}
#endif
-bool Scheduler::canBeDispatched(const InstRef &IR,
- Scheduler::StallKind &Event) const {
- Event = StallKind::NoStall;
+Scheduler::Status Scheduler::isAvailable(const InstRef &IR) const {
const InstrDesc &Desc = IR.getInstruction()->getDesc();
-
- // Give lower priority to these stall events.
- if (Desc.MayStore && LSU->isSQFull())
- Event = StallKind::StoreQueueFull;
- if (Desc.MayLoad && LSU->isLQFull())
- Event = StallKind::LoadQueueFull;
-
+
switch (Resources->canBeDispatched(Desc.Buffers)) {
case ResourceStateEvent::RS_BUFFER_UNAVAILABLE:
- Event = StallKind::SchedulerQueueFull;
- break;
+ return Scheduler::SC_BUFFERS_FULL;
case ResourceStateEvent::RS_RESERVED:
- Event = StallKind::DispatchGroupStall;
- break;
- default:
+ return Scheduler::SC_DISPATCH_GROUP_STALL;
+ case ResourceStateEvent::RS_BUFFER_AVAILABLE:
break;
}
- return Event == StallKind::NoStall;
+ // Give lower priority to LSUnit stall events.
+ switch (LSU->isAvailable(IR)) {
+ case LSUnit::LSU_LQUEUE_FULL:
+ return Scheduler::SC_LOAD_QUEUE_FULL;
+ case LSUnit::LSU_SQUEUE_FULL:
+ return Scheduler::SC_STORE_QUEUE_FULL;
+ case LSUnit::LSU_AVAILABLE:
+ return Scheduler::SC_AVAILABLE;
+ }
+
+ llvm_unreachable("Don't know how to process this LSU state result!");
}
void Scheduler::issueInstructionImpl(
@@ -298,6 +298,8 @@ void Scheduler::issueInstructionImpl(
if (IS->isExecuting())
IssuedSet.emplace_back(IR);
+ else if (IS->isExecuted())
+ LSU->onInstructionExecuted(IR);
}
// Release the buffered resources and issue the instruction.
@@ -305,7 +307,7 @@ void Scheduler::issueInstruction(
InstRef &IR,
SmallVectorImpl<std::pair<ResourceRef, double>> &UsedResources) {
const InstrDesc &Desc = IR.getInstruction()->getDesc();
- releaseBuffers(Desc.Buffers);
+ Resources->releaseBuffers(Desc.Buffers);
issueInstructionImpl(IR, UsedResources);
}
@@ -324,9 +326,8 @@ void Scheduler::promoteToReadySet(SmallV
if (!IS.isReady())
IS.update();
- const InstrDesc &Desc = IS.getDesc();
- bool IsMemOp = Desc.MayLoad || Desc.MayStore;
- if (!IS.isReady() || (IsMemOp && !LSU->isReady(IR))) {
+ // Check f there are still unsolved data dependencies.
+ if (!isReady(IR)) {
++I;
continue;
}
@@ -405,6 +406,8 @@ void Scheduler::updateIssuedSet(SmallVec
continue;
}
+ // Instruction IR has completed execution.
+ LSU->onInstructionExecuted(IR);
Executed.emplace_back(IR);
++RemovedElements;
IR.invalidate();
@@ -414,33 +417,51 @@ void Scheduler::updateIssuedSet(SmallVec
IssuedSet.resize(IssuedSet.size() - RemovedElements);
}
-void Scheduler::onInstructionExecuted(const InstRef &IR) {
- LSU->onInstructionExecuted(IR);
-}
-
void Scheduler::reclaimSimulatedResources(SmallVectorImpl<ResourceRef> &Freed) {
Resources->cycleEvent(Freed);
}
-bool Scheduler::reserveResources(InstRef &IR) {
+bool Scheduler::mustIssueImmediately(const InstRef &IR) const {
+ // Instructions that use an in-order dispatch/issue processor resource must be
+ // issued immediately to the pipeline(s). Any other in-order buffered
+ // resources (i.e. BufferSize=1) is consumed.
+ const InstrDesc &Desc = IR.getInstruction()->getDesc();
+ return Desc.isZeroLatency() || Resources->mustIssueImmediately(Desc);
+}
+
+void Scheduler::dispatch(const InstRef &IR) {
+ const InstrDesc &Desc = IR.getInstruction()->getDesc();
+ Resources->reserveBuffers(Desc.Buffers);
+
// If necessary, reserve queue entries in the load-store unit (LSU).
- const bool Reserved = LSU->reserve(IR);
- if (!IR.getInstruction()->isReady() || (Reserved && !LSU->isReady(IR))) {
+ bool IsMemOp = Desc.MayLoad || Desc.MayStore;
+ if (IsMemOp)
+ LSU->dispatch(IR);
+
+ if (!isReady(IR)) {
LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR << " to the WaitSet\n");
WaitSet.push_back(IR);
- return false;
+ return;
}
- return true;
-}
-bool Scheduler::issueImmediately(InstRef &IR) {
- const InstrDesc &Desc = IR.getInstruction()->getDesc();
- if (!Desc.isZeroLatency() && !Resources->mustIssueImmediately(Desc)) {
+ // Don't add a zero-latency instruction to the Ready queue.
+ // A zero-latency instruction doesn't consume any scheduler resources. That is
+ // because it doesn't need to be executed, and it is often removed at register
+ // renaming stage. For example, register-register moves are often optimized at
+ // register renaming stage by simply updating register aliases. On some
+ // targets, zero-idiom instructions (for example: a xor that clears the value
+ // of a register) are treated specially, and are often eliminated at register
+ // renaming stage.
+ if (!mustIssueImmediately(IR)) {
LLVM_DEBUG(dbgs() << "[SCHEDULER] Adding #" << IR << " to the ReadySet\n");
ReadySet.push_back(IR);
- return false;
}
- return true;
+}
+
+bool Scheduler::isReady(const InstRef &IR) const {
+ const InstrDesc &Desc = IR.getInstruction()->getDesc();
+ bool IsMemOp = Desc.MayLoad || Desc.MayStore;
+ return IR.getInstruction()->isReady() && (!IsMemOp || LSU->isReady(IR));
}
} // namespace mca
Modified: llvm/trunk/tools/llvm-mca/Scheduler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/Scheduler.h?rev=340176&r1=340175&r2=340176&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/Scheduler.h (original)
+++ llvm/trunk/tools/llvm-mca/Scheduler.h Mon Aug 20 07:41:36 2018
@@ -321,7 +321,7 @@ public:
// Returns true if all resources are in-order, and there is at least one
// resource which is a dispatch hazard (BufferSize = 0).
- bool mustIssueImmediately(const InstrDesc &Desc);
+ bool mustIssueImmediately(const InstrDesc &Desc) const;
bool canBeIssued(const InstrDesc &Desc) const;
@@ -364,10 +364,10 @@ public:
/// leaves the IssuedSet when it reaches the write-back stage.
class Scheduler : public HardwareUnit {
const llvm::MCSchedModel &SM;
+ LSUnit *LSU;
// Hardware resources that are managed by this scheduler.
std::unique_ptr<ResourceManager> Resources;
- std::unique_ptr<LSUnit> LSU;
std::vector<InstRef> WaitSet;
std::vector<InstRef> ReadySet;
@@ -379,54 +379,49 @@ class Scheduler : public HardwareUnit {
llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Pipes);
public:
- Scheduler(const llvm::MCSchedModel &Model, unsigned LoadQueueSize,
- unsigned StoreQueueSize, bool AssumeNoAlias)
- : SM(Model), Resources(llvm::make_unique<ResourceManager>(SM)),
- LSU(llvm::make_unique<LSUnit>(LoadQueueSize, StoreQueueSize,
- AssumeNoAlias)) {}
+ Scheduler(const llvm::MCSchedModel &Model, LSUnit *Lsu)
+ : SM(Model), LSU(Lsu), Resources(llvm::make_unique<ResourceManager>(SM)) {
+ }
// Stalls generated by the scheduler.
- enum StallKind {
- NoStall,
- LoadQueueFull,
- StoreQueueFull,
- SchedulerQueueFull,
- DispatchGroupStall
+ enum Status {
+ SC_AVAILABLE,
+ SC_LOAD_QUEUE_FULL,
+ SC_STORE_QUEUE_FULL,
+ SC_BUFFERS_FULL,
+ SC_DISPATCH_GROUP_STALL,
};
- /// Check if the instruction in 'IR' can be dispatched.
+ /// Check if the instruction in 'IR' can be dispatched and returns an answer
+ /// in the form of a Status value.
///
/// The DispatchStage is responsible for querying the Scheduler before
/// dispatching new instructions. This routine is used for performing such
/// a query. If the instruction 'IR' can be dispatched, then true is
/// returned, otherwise false is returned with Event set to the stall type.
- bool canBeDispatched(const InstRef &IR, StallKind &Event) const;
+ /// Internally, it also checks if the load/store unit is available.
+ Status isAvailable(const InstRef &IR) const;
- /// Returns true if there is availibility for IR in the LSU.
- bool isReady(const InstRef &IR) const { return LSU->isReady(IR); }
+ /// Reserves buffer and LSUnit queue resources that are necessary to issue
+ /// this instruction.
+ ///
+ /// Returns true if instruction IR is ready to be issued to the underlying
+ /// pipelines. Note that this operation cannot fail; it assumes that a
+ /// previous call to method `isAvailable(IR)` returned `SC_AVAILABLE`.
+ void dispatch(const InstRef &IR);
+
+ /// Returns true if IR is ready to be executed by the underlying pipelines.
+ /// This method assumes that IR has been previously dispatched.
+ bool isReady(const InstRef &IR) const;
/// Issue an instruction. The Used container is populated with
/// the resource objects consumed on behalf of issuing this instruction.
- void
- issueInstruction(InstRef &IR,
+ void issueInstruction(InstRef &IR,
llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Used);
- /// This routine will attempt to issue an instruction immediately (for
- /// zero-latency instructions).
- ///
- /// Returns true if the instruction is issued immediately. If this does not
- /// occur, then the instruction will be added to the Scheduler's ReadySet.
- bool issueImmediately(InstRef &IR);
-
- /// Reserve one entry in each buffered resource.
- void reserveBuffers(llvm::ArrayRef<uint64_t> Buffers) {
- Resources->reserveBuffers(Buffers);
- }
-
- /// Release buffer entries previously allocated by method reserveBuffers.
- void releaseBuffers(llvm::ArrayRef<uint64_t> Buffers) {
- Resources->releaseBuffers(Buffers);
- }
+ /// Returns true if IR has to be issued immediately, or if IR is a zero
+ /// latency instruction.
+ bool mustIssueImmediately(const InstRef &IR) const;
/// Update the resources managed by the scheduler.
/// This routine is to be called at the start of a new cycle, and is
@@ -444,21 +439,12 @@ public:
/// Update the issued queue.
void updateIssuedSet(llvm::SmallVectorImpl<InstRef> &Executed);
- /// Updates the Scheduler's resources to reflect that an instruction has just
- /// been executed.
- void onInstructionExecuted(const InstRef &IR);
-
/// Obtain the processor's resource identifier for the given
/// resource mask.
unsigned getResourceID(uint64_t Mask) {
return Resources->resolveResourceMask(Mask);
}
- /// Reserve resources necessary to issue the instruction.
- /// Returns true if the resources are ready and the (LSU) can
- /// execute the given instruction immediately.
- bool reserveResources(InstRef &IR);
-
/// Select the next instruction to issue from the ReadySet.
/// This method gives priority to older instructions.
InstRef select();
More information about the llvm-commits
mailing list