1 //===--------------------- DispatchStage.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 models the dispatch component of an instruction pipeline.
13 /// The DispatchStage is responsible for updating instruction dependencies
14 /// and communicating to the simulated instruction scheduler that an instruction
15 /// is ready to be scheduled for execution.
17 //===----------------------------------------------------------------------===//
19 #include "DispatchStage.h"
20 #include "HWEventListener.h"
21 #include "Scheduler.h"
22 #include "llvm/Support/Debug.h"
26 #define DEBUG_TYPE "llvm-mca"
30 void DispatchStage::notifyInstructionDispatched(const InstRef &IR,
31 ArrayRef<unsigned> UsedRegs) {
32 LLVM_DEBUG(dbgs() << "[E] Instruction Dispatched: #" << IR << '\n');
33 notifyEvent<HWInstructionEvent>(HWInstructionDispatchedEvent(IR, UsedRegs));
36 bool DispatchStage::checkPRF(const InstRef &IR) {
37 SmallVector<unsigned, 4> RegDefs;
38 for (const std::unique_ptr<WriteState> &RegDef :
39 IR.getInstruction()->getDefs())
40 RegDefs.emplace_back(RegDef->getRegisterID());
42 const unsigned RegisterMask = PRF.isAvailable(RegDefs);
43 // A mask with all zeroes means: register files are available.
45 notifyEvent<HWStallEvent>(
46 HWStallEvent(HWStallEvent::RegisterFileStall, IR));
53 bool DispatchStage::checkRCU(const InstRef &IR) {
54 const unsigned NumMicroOps = IR.getInstruction()->getDesc().NumMicroOps;
55 if (RCU.isAvailable(NumMicroOps))
57 notifyEvent<HWStallEvent>(
58 HWStallEvent(HWStallEvent::RetireControlUnitStall, IR));
62 bool DispatchStage::checkScheduler(const InstRef &IR) {
63 HWStallEvent::GenericEventType Event;
64 const bool Ready = SC.canBeDispatched(IR, Event);
66 notifyEvent<HWStallEvent>(HWStallEvent(Event, IR));
70 void DispatchStage::updateRAWDependencies(ReadState &RS,
71 const MCSubtargetInfo &STI) {
72 SmallVector<WriteRef, 4> DependentWrites;
74 collectWrites(DependentWrites, RS.getRegisterID());
75 RS.setDependentWrites(DependentWrites.size());
76 // We know that this read depends on all the writes in DependentWrites.
77 // For each write, check if we have ReadAdvance information, and use it
78 // to figure out in how many cycles this read becomes available.
79 const ReadDescriptor &RD = RS.getDescriptor();
80 const MCSchedModel &SM = STI.getSchedModel();
81 const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
82 for (WriteRef &WR : DependentWrites) {
83 WriteState &WS = *WR.getWriteState();
84 unsigned WriteResID = WS.getWriteResourceID();
85 int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
86 WS.addUser(&RS, ReadAdvance);
90 void DispatchStage::dispatch(InstRef IR) {
91 assert(!CarryOver && "Cannot dispatch another instruction!");
92 Instruction &IS = *IR.getInstruction();
93 const InstrDesc &Desc = IS.getDesc();
94 const unsigned NumMicroOps = Desc.NumMicroOps;
95 if (NumMicroOps > DispatchWidth) {
96 assert(AvailableEntries == DispatchWidth);
98 CarryOver = NumMicroOps - DispatchWidth;
100 assert(AvailableEntries >= NumMicroOps);
101 AvailableEntries -= NumMicroOps;
104 // A dependency-breaking instruction doesn't have to wait on the register
105 // input operands, and it is often optimized at register renaming stage.
106 // Update RAW dependencies if this instruction is not a dependency-breaking
107 // instruction. A dependency-breaking instruction is a zero-latency
108 // instruction that doesn't consume hardware resources.
109 // An example of dependency-breaking instruction on X86 is a zero-idiom XOR.
110 bool IsDependencyBreaking = IS.isDependencyBreaking();
111 for (std::unique_ptr<ReadState> &RS : IS.getUses())
112 if (RS->isImplicitRead() || !IsDependencyBreaking)
113 updateRAWDependencies(*RS, STI);
115 // By default, a dependency-breaking zero-latency instruction is expected to
116 // be optimized at register renaming stage. That means, no physical register
117 // is allocated to the instruction.
118 bool ShouldAllocateRegisters =
119 !(Desc.isZeroLatency() && IsDependencyBreaking);
120 SmallVector<unsigned, 4> RegisterFiles(PRF.getNumRegisterFiles());
121 for (std::unique_ptr<WriteState> &WS : IS.getDefs()) {
122 PRF.addRegisterWrite(WriteRef(IR.first, WS.get()), RegisterFiles,
123 ShouldAllocateRegisters);
126 // Reserve slots in the RCU, and notify the instruction that it has been
127 // dispatched to the schedulers for execution.
128 IS.dispatch(RCU.reserveSlot(IR, NumMicroOps));
130 // Notify listeners of the "instruction dispatched" event.
131 notifyInstructionDispatched(IR, RegisterFiles);
134 void DispatchStage::cycleStart() {
135 AvailableEntries = CarryOver >= DispatchWidth ? 0 : DispatchWidth - CarryOver;
136 CarryOver = CarryOver >= DispatchWidth ? CarryOver - DispatchWidth : 0U;
139 bool DispatchStage::execute(InstRef &IR) {
140 const InstrDesc &Desc = IR.getInstruction()->getDesc();
141 if (!isAvailable(Desc.NumMicroOps) || !canDispatch(IR))
148 void DispatchStage::dump() const {