]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-mca/DispatchStage.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / llvm-mca / DispatchStage.cpp
1 //===--------------------- DispatchStage.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 models the dispatch component of an instruction pipeline.
12 ///
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.
16 ///
17 //===----------------------------------------------------------------------===//
18
19 #include "DispatchStage.h"
20 #include "HWEventListener.h"
21 #include "Scheduler.h"
22 #include "llvm/Support/Debug.h"
23
24 using namespace llvm;
25
26 #define DEBUG_TYPE "llvm-mca"
27
28 namespace mca {
29
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));
34 }
35
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());
41
42   const unsigned RegisterMask = PRF.isAvailable(RegDefs);
43   // A mask with all zeroes means: register files are available.
44   if (RegisterMask) {
45     notifyEvent<HWStallEvent>(
46         HWStallEvent(HWStallEvent::RegisterFileStall, IR));
47     return false;
48   }
49
50   return true;
51 }
52
53 bool DispatchStage::checkRCU(const InstRef &IR) {
54   const unsigned NumMicroOps = IR.getInstruction()->getDesc().NumMicroOps;
55   if (RCU.isAvailable(NumMicroOps))
56     return true;
57   notifyEvent<HWStallEvent>(
58       HWStallEvent(HWStallEvent::RetireControlUnitStall, IR));
59   return false;
60 }
61
62 bool DispatchStage::checkScheduler(const InstRef &IR) {
63   HWStallEvent::GenericEventType Event;
64   const bool Ready = SC.canBeDispatched(IR, Event);
65   if (!Ready)
66     notifyEvent<HWStallEvent>(HWStallEvent(Event, IR));
67   return Ready;
68 }
69
70 void DispatchStage::updateRAWDependencies(ReadState &RS,
71                                           const MCSubtargetInfo &STI) {
72   SmallVector<WriteRef, 4> DependentWrites;
73
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);
87   }
88 }
89
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);
97     AvailableEntries = 0;
98     CarryOver = NumMicroOps - DispatchWidth;
99   } else {
100     assert(AvailableEntries >= NumMicroOps);
101     AvailableEntries -= NumMicroOps;
102   }
103
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);
114
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);
124   }
125
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));
129
130   // Notify listeners of the "instruction dispatched" event.
131   notifyInstructionDispatched(IR, RegisterFiles);
132 }
133
134 void DispatchStage::cycleStart() {
135   AvailableEntries = CarryOver >= DispatchWidth ? 0 : DispatchWidth - CarryOver;
136   CarryOver = CarryOver >= DispatchWidth ? CarryOver - DispatchWidth : 0U;
137 }
138
139 bool DispatchStage::execute(InstRef &IR) {
140   const InstrDesc &Desc = IR.getInstruction()->getDesc();
141   if (!isAvailable(Desc.NumMicroOps) || !canDispatch(IR))
142     return false;
143   dispatch(IR);
144   return true;
145 }
146
147 #ifndef NDEBUG
148 void DispatchStage::dump() const {
149   PRF.dump();
150   RCU.dump();
151 }
152 #endif
153 } // namespace mca