20#define DEBUG_TYPE "llvm-mca"
49 : STI(STI), PRF(PRF), RM(STI.getSchedModel()), CB(CB), LSU(LSU),
50 NumIssued(), CarryOver(), Bandwidth(), LastWriteBackCycle() {}
57 return !IssuedInst.empty() || SI.
isValid() || CarriedOver;
61 if (SI.
isValid() || CarriedOver)
68 if (Bandwidth < NumMicroOps && !ShouldCarryOver)
80 if (RM.checkAvailability(
IR.getInstruction()->getDesc())) {
89 unsigned FirstWBCycle =
IR.getInstruction()->getLatency();
90 for (
const WriteState &WS :
IR.getInstruction()->getDefs()) {
91 int CyclesLeft = WS.getCyclesLeft();
93 CyclesLeft = WS.getLatency();
96 FirstWBCycle = std::min(FirstWBCycle, (
unsigned)CyclesLeft);
106 for (
const ReadState &RS :
IR.getInstruction()->getUses()) {
115bool InOrderIssueStage::canExecute(
const InstRef &
IR) {
117 assert(!SI.
isValid() &&
"Should not have reached this code!");
129 if (
IR.getInstruction()->isMemOp() && !LSU.
isReady(
IR)) {
141 if (LastWriteBackCycle) {
142 if (!
IR.getInstruction()->getRetireOOO()) {
145 if (NextWriteBackCycle < LastWriteBackCycle) {
146 SI.
update(
IR, LastWriteBackCycle - NextWriteBackCycle,
157 unsigned SourceIndex,
169void InOrderIssueStage::notifyInstructionIssued(
const InstRef &
IR,
171 notifyEvent<HWInstructionEvent>(
173 notifyEvent<HWInstructionEvent>(HWInstructionIssuedEvent(
IR, UsedRes));
178void InOrderIssueStage::notifyInstructionDispatched(
179 const InstRef &
IR,
unsigned Ops, ArrayRef<unsigned> UsedRegs) {
180 notifyEvent<HWInstructionEvent>(
181 HWInstructionDispatchedEvent(
IR, UsedRegs, Ops));
186void InOrderIssueStage::notifyInstructionExecuted(
const InstRef &
IR) {
187 notifyEvent<HWInstructionEvent>(
192void InOrderIssueStage::notifyInstructionRetired(
const InstRef &
IR,
193 ArrayRef<unsigned> FreedRegs) {
194 notifyEvent<HWInstructionEvent>(HWInstructionRetiredEvent(
IR, FreedRegs));
214 unsigned SourceIndex =
IR.getSourceIndex();
217 if (!canExecute(
IR)) {
231 notifyInstructionDispatched(
IR, NumMicroOps, UsedRegs);
245 notifyInstructionIssued(
IR, UsedResources);
247 bool ShouldCarryOver = NumMicroOps > Bandwidth;
248 if (ShouldCarryOver) {
249 CarryOver = NumMicroOps - Bandwidth;
252 NumIssued += Bandwidth;
255 NumIssued += NumMicroOps;
256 Bandwidth = IS.
getEndGroup() ? 0 : Bandwidth - NumMicroOps;
266 notifyInstructionExecuted(
IR);
268 retireInstruction(
IR);
272 IssuedInst.push_back(
IR);
274 if (!
IR.getInstruction()->getRetireOOO())
280void InOrderIssueStage::updateIssuedInst() {
283 unsigned NumExecuted = 0;
284 for (
auto I = IssuedInst.begin(),
E = IssuedInst.end();
285 I != (
E - NumExecuted);) {
287 Instruction &IS = *
IR.getInstruction();
290 if (!IS.isExecuted()) {
292 <<
" is still executing\n");
303 notifyInstructionExecuted(
IR);
305 retireInstruction(*
I);
310 std::iter_swap(
I,
E - NumExecuted);
314 IssuedInst.resize(IssuedInst.size() - NumExecuted);
317void InOrderIssueStage::updateCarriedOver() {
321 assert(!SI.
isValid() &&
"A stalled instruction cannot be carried over.");
323 if (CarryOver > Bandwidth) {
324 CarryOver -= Bandwidth;
326 LLVM_DEBUG(
dbgs() <<
"[N] Carry over (" << CarryOver <<
"uops left) #"
327 << CarriedOver <<
" \n");
331 LLVM_DEBUG(
dbgs() <<
"[N] Carry over (complete) #" << CarriedOver <<
" \n");
336 Bandwidth -= CarryOver;
343 notifyInstructionExecuted(CarriedOver);
345 retireInstruction(CarriedOver);
348 CarriedOver = InstRef();
352void InOrderIssueStage::retireInstruction(InstRef &
IR) {
353 Instruction &IS = *
IR.getInstruction();
357 for (
const WriteState &WS : IS.getDefs())
363 notifyInstructionRetired(
IR, FreedRegs);
366void InOrderIssueStage::notifyStallEvent() {
376 notifyEvent<HWStallEvent>(
378 notifyEvent<HWPressureEvent>(
383 notifyEvent<HWStallEvent>(
385 notifyEvent<HWPressureEvent>(
390 notifyEvent<HWStallEvent>(
443 if (LastWriteBackCycle > 0)
444 --LastWriteBackCycle;
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
InOrderIssueStage implements an in-order execution pipeline.
A Load/Store unit class that models load/store queues and that implements a simple weak memory consis...
Legalize the Machine IR a function s Machine IR
This file defines abstractions used by the Pipeline to model register reads, register writes and inst...
This file defines a register mapping file class.
This file simulates the hardware responsible for retiring instructions.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Subclass of Error for the sole purpose of identifying the success path in the type system.
Lightweight error class with error context and mandatory checking.
Generic base class for all target subtargets.
const MCSchedModel & getSchedModel() const
Get the machine model for this subtarget's CPU.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A Use represents the edge between a Value definition and its users.
Class which can be overriden by targets to enforce instruction dependencies and behaviours that aren'...
virtual unsigned checkCustomHazard(ArrayRef< InstRef > IssuedInst, const InstRef &IR)
Before the llvm-mca pipeline dispatches an instruction, it first checks for any register or resource ...
bool hasWorkToComplete() const override
Returns true if some instructions are still executing this stage.
Error cycleEnd() override
Called once at the end of each cycle.
Error execute(InstRef &IR) override
The primary action that this stage performs on instruction IR.
bool isAvailable(const InstRef &) const override
Returns true if it can execute IR during this cycle.
unsigned getIssueWidth() const
Error cycleStart() override
Called once at the start of each cycle.
An InstRef contains both a SourceMgr index and Instruction pair.
void invalidate()
Invalidate this reference.
Instruction * getInstruction()
unsigned getNumMicroOps() const
const InstrDesc & getDesc() const
SmallVectorImpl< WriteState > & getDefs()
SmallVectorImpl< ReadState > & getUses()
bool getBeginGroup() const
An instruction propagated through the simulated instruction pipeline.
bool isEliminated() const
int getCyclesLeft() const
void execute(unsigned IID)
void setLSUTokenID(unsigned LSUTok)
void dispatch(unsigned RCUTokenID)
Abstract base interface for LS (load/store) units in llvm-mca.
virtual unsigned dispatch(const InstRef &IR)=0
Allocates LS resources for instruction IR.
virtual bool isReady(const InstRef &IR) const =0
Check if a peviously dispatched instruction IR is now ready for execution.
virtual void onInstructionRetired(const InstRef &IR)=0
virtual void onInstructionExecuted(const InstRef &IR)=0
virtual void cycleEvent()=0
virtual void onInstructionIssued(const InstRef &IR)=0
Tracks register operand latency in cycles.
Manages hardware register files, and tracks register definitions for register renaming purposes.
void addRegisterWrite(WriteRef Write, MutableArrayRef< unsigned > UsedPhysRegs)
unsigned getNumRegisterFiles() const
RAWHazard checkRAWHazards(const MCSubtargetInfo &STI, const ReadState &RS) const
void removeRegisterWrite(const WriteState &WS, MutableArrayRef< unsigned > FreedPhysRegs)
void addRegisterRead(ReadState &RS, const MCSubtargetInfo &STI) const
void onInstructionExecuted(Instruction *IS)
A resource manager for processor resource units and groups.
void issueInstruction(const InstrDesc &Desc, SmallVectorImpl< ResourceWithCycles > &Pipes)
unsigned resolveResourceMask(uint64_t Mask) const
void cycleEvent(SmallVectorImpl< ResourceRef > &ResourcesFreed)
A reference to a register write.
Tracks uses of a register definition (e.g.
std::pair< ResourceRef, ReleaseAtCycles > ResourceUse
static void addRegisterReadWrite(RegisterFile &PRF, Instruction &IS, unsigned SourceIndex, const MCSubtargetInfo &STI, SmallVectorImpl< unsigned > &UsedRegs)
static bool hasResourceHazard(const ResourceManager &RM, const InstRef &IR)
static unsigned findFirstWriteBackCycle(const InstRef &IR)
static unsigned checkRegisterHazard(const RegisterFile &PRF, const MCSubtargetInfo &STI, const InstRef &IR)
Return a number of cycles left until register requirements of the instructions are met.
constexpr int UNKNOWN_CYCLES
This is an optimization pass for GlobalISel generic memory operations.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Description of the encoding of one expression Op.
An instruction descriptor.
bool hasUnknownCycles() const
static const unsigned UnhandledTokenID
StallKind getStallKind() const
const InstRef & getInstruction() const
unsigned getCyclesLeft() const
void update(const InstRef &Inst, unsigned Cycles, StallKind SK)