OSDN Git Service

01bd52f793f7e431c4fd9253255bc488616d5d98
[android-x86/external-llvm.git] / tools / llvm-mca / DispatchStage.cpp
1 //===--------------------- Dispatch.cpp -------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 ///
11 /// This file implements methods declared by the DispatchStage class.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #include "DispatchStage.h"
16 #include "Backend.h"
17 #include "HWEventListener.h"
18 #include "Scheduler.h"
19 #include "llvm/Support/Debug.h"
20
21 using namespace llvm;
22
23 #define DEBUG_TYPE "llvm-mca"
24
25 namespace mca {
26
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));
31 }
32
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();
37
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));
41 }
42
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());
48
49   unsigned RegisterMask = RAT->isAvailable(RegDefs);
50   // A mask with all zeroes means: register files are available.
51   if (RegisterMask) {
52     Owner->notifyStallEvent(HWStallEvent(HWStallEvent::RegisterFileStall, IR));
53     return false;
54   }
55
56   return true;
57 }
58
59 bool DispatchStage::checkRCU(const InstRef &IR) {
60   const unsigned NumMicroOps = IR.getInstruction()->getDesc().NumMicroOps;
61   if (RCU->isAvailable(NumMicroOps))
62     return true;
63   Owner->notifyStallEvent(
64       HWStallEvent(HWStallEvent::RetireControlUnitStall, IR));
65   return false;
66 }
67
68 bool DispatchStage::checkScheduler(const InstRef &IR) {
69   return SC->canBeDispatched(IR);
70 }
71
72 void DispatchStage::updateRAWDependencies(ReadState &RS,
73                                           const MCSubtargetInfo &STI) {
74   SmallVector<WriteState *, 4> DependentWrites;
75
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);
87     return;
88   }
89
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);
96   }
97   // Prepare the set for another round.
98   DependentWrites.clear();
99 }
100
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;
110   } else {
111     assert(AvailableEntries >= NumMicroOps);
112     AvailableEntries -= NumMicroOps;
113   }
114
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);
124
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());
131
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));
135
136   // Notify listeners of the "instruction dispatched" event.
137   notifyInstructionDispatched(IR, RegisterFiles);
138
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);
143 }
144
145 void DispatchStage::preExecute(const InstRef &IR) {
146   RCU->cycleEvent();
147   AvailableEntries = CarryOver >= DispatchWidth ? 0 : DispatchWidth - CarryOver;
148   CarryOver = CarryOver >= DispatchWidth ? CarryOver - DispatchWidth : 0U;
149 }
150
151 bool DispatchStage::execute(InstRef &IR) {
152   const InstrDesc &Desc = IR.getInstruction()->getDesc();
153   if (!isAvailable(Desc.NumMicroOps) || !canDispatch(IR))
154     return false;
155   dispatch(IR);
156   return true;
157 }
158
159 #ifndef NDEBUG
160 void DispatchStage::dump() const {
161   RAT->dump();
162   RCU->dump();
163 }
164 #endif
165 } // namespace mca