1 //===--------------------- Dispatch.cpp -------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// This file implements methods declared by the DispatchStage class.
13 //===----------------------------------------------------------------------===//
15 #include "DispatchStage.h"
17 #include "HWEventListener.h"
18 #include "Scheduler.h"
19 #include "llvm/Support/Debug.h"
23 #define DEBUG_TYPE "llvm-mca"
27 void DispatchStage::notifyInstructionDispatched(const InstRef &IR,
28 ArrayRef<unsigned> UsedRegs) {
29 LLVM_DEBUG(dbgs() << "[E] Instruction Dispatched: " << IR << '\n');
30 Owner->notifyInstructionEvent(HWInstructionDispatchedEvent(IR, UsedRegs));
33 void DispatchStage::notifyInstructionRetired(const InstRef &IR) {
34 LLVM_DEBUG(dbgs() << "[E] Instruction Retired: " << IR << '\n');
35 SmallVector<unsigned, 4> FreedRegs(RAT->getNumRegisterFiles());
36 const InstrDesc &Desc = IR.getInstruction()->getDesc();
38 for (const std::unique_ptr<WriteState> &WS : IR.getInstruction()->getDefs())
39 RAT->removeRegisterWrite(*WS.get(), FreedRegs, !Desc.isZeroLatency());
40 Owner->notifyInstructionEvent(HWInstructionRetiredEvent(IR, FreedRegs));
43 bool DispatchStage::checkRAT(const InstRef &IR) {
44 SmallVector<unsigned, 4> RegDefs;
45 for (const std::unique_ptr<WriteState> &RegDef :
46 IR.getInstruction()->getDefs())
47 RegDefs.emplace_back(RegDef->getRegisterID());
49 unsigned RegisterMask = RAT->isAvailable(RegDefs);
50 // A mask with all zeroes means: register files are available.
52 Owner->notifyStallEvent(HWStallEvent(HWStallEvent::RegisterFileStall, IR));
59 bool DispatchStage::checkRCU(const InstRef &IR) {
60 const unsigned NumMicroOps = IR.getInstruction()->getDesc().NumMicroOps;
61 if (RCU->isAvailable(NumMicroOps))
63 Owner->notifyStallEvent(
64 HWStallEvent(HWStallEvent::RetireControlUnitStall, IR));
68 bool DispatchStage::checkScheduler(const InstRef &IR) {
69 return SC->canBeDispatched(IR);
72 void DispatchStage::updateRAWDependencies(ReadState &RS,
73 const MCSubtargetInfo &STI) {
74 SmallVector<WriteState *, 4> DependentWrites;
76 collectWrites(DependentWrites, RS.getRegisterID());
77 RS.setDependentWrites(DependentWrites.size());
78 LLVM_DEBUG(dbgs() << "Found " << DependentWrites.size()
79 << " dependent writes\n");
80 // We know that this read depends on all the writes in DependentWrites.
81 // For each write, check if we have ReadAdvance information, and use it
82 // to figure out in how many cycles this read becomes available.
83 const ReadDescriptor &RD = RS.getDescriptor();
84 if (!RD.HasReadAdvanceEntries) {
85 for (WriteState *WS : DependentWrites)
86 WS->addUser(&RS, /* ReadAdvance */ 0);
90 const MCSchedModel &SM = STI.getSchedModel();
91 const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
92 for (WriteState *WS : DependentWrites) {
93 unsigned WriteResID = WS->getWriteResourceID();
94 int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
95 WS->addUser(&RS, ReadAdvance);
97 // Prepare the set for another round.
98 DependentWrites.clear();
101 void DispatchStage::dispatch(InstRef IR) {
102 assert(!CarryOver && "Cannot dispatch another instruction!");
103 Instruction &IS = *IR.getInstruction();
104 const InstrDesc &Desc = IS.getDesc();
105 const unsigned NumMicroOps = Desc.NumMicroOps;
106 if (NumMicroOps > DispatchWidth) {
107 assert(AvailableEntries == DispatchWidth);
108 AvailableEntries = 0;
109 CarryOver = NumMicroOps - DispatchWidth;
111 assert(AvailableEntries >= NumMicroOps);
112 AvailableEntries -= NumMicroOps;
115 // A dependency-breaking instruction doesn't have to wait on the register
116 // input operands, and it is often optimized at register renaming stage.
117 // Update RAW dependencies if this instruction is not a dependency-breaking
118 // instruction. A dependency-breaking instruction is a zero-latency
119 // instruction that doesn't consume hardware resources.
120 // An example of dependency-breaking instruction on X86 is a zero-idiom XOR.
121 if (!Desc.isZeroLatency())
122 for (std::unique_ptr<ReadState> &RS : IS.getUses())
123 updateRAWDependencies(*RS, STI);
125 // By default, a dependency-breaking zero-latency instruction is expected to
126 // be optimized at register renaming stage. That means, no physical register
127 // is allocated to the instruction.
128 SmallVector<unsigned, 4> RegisterFiles(RAT->getNumRegisterFiles());
129 for (std::unique_ptr<WriteState> &WS : IS.getDefs())
130 RAT->addRegisterWrite(*WS, RegisterFiles, !Desc.isZeroLatency());
132 // Reserve slots in the RCU, and notify the instruction that it has been
133 // dispatched to the schedulers for execution.
134 IS.dispatch(RCU->reserveSlot(IR, NumMicroOps));
136 // Notify listeners of the "instruction dispatched" event.
137 notifyInstructionDispatched(IR, RegisterFiles);
139 // Now move the instruction into the scheduler's queue.
140 // The scheduler is responsible for checking if this is a zero-latency
141 // instruction that doesn't consume pipeline/scheduler resources.
142 SC->scheduleInstruction(IR);
145 void DispatchStage::preExecute(const InstRef &IR) {
147 AvailableEntries = CarryOver >= DispatchWidth ? 0 : DispatchWidth - CarryOver;
148 CarryOver = CarryOver >= DispatchWidth ? CarryOver - DispatchWidth : 0U;
151 bool DispatchStage::execute(InstRef &IR) {
152 const InstrDesc &Desc = IR.getInstruction()->getDesc();
153 if (!isAvailable(Desc.NumMicroOps) || !canDispatch(IR))
160 void DispatchStage::dump() const {