LLVM  8.0.1
DispatchStage.cpp
Go to the documentation of this file.
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 
22 #include "llvm/Support/Debug.h"
23 
24 #define DEBUG_TYPE "llvm-mca"
25 
26 namespace llvm {
27 namespace mca {
28 
29 void DispatchStage::notifyInstructionDispatched(const InstRef &IR,
30  ArrayRef<unsigned> UsedRegs,
31  unsigned UOps) const {
32  LLVM_DEBUG(dbgs() << "[E] Instruction Dispatched: #" << IR << '\n');
33  notifyEvent<HWInstructionEvent>(
34  HWInstructionDispatchedEvent(IR, UsedRegs, UOps));
35 }
36 
37 bool DispatchStage::checkPRF(const InstRef &IR) const {
38  SmallVector<unsigned, 4> RegDefs;
39  for (const WriteState &RegDef : 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) const {
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::canDispatch(const InstRef &IR) const {
63  return checkRCU(IR) && checkPRF(IR) && checkNextStage(IR);
64 }
65 
66 void DispatchStage::updateRAWDependencies(ReadState &RS,
67  const MCSubtargetInfo &STI) {
68  SmallVector<WriteRef, 4> DependentWrites;
69 
70  // Collect all the dependent writes, and update RS internal state.
71  PRF.addRegisterRead(RS, DependentWrites);
72 
73  // We know that this read depends on all the writes in DependentWrites.
74  // For each write, check if we have ReadAdvance information, and use it
75  // to figure out in how many cycles this read becomes available.
76  const ReadDescriptor &RD = RS.getDescriptor();
77  const MCSchedModel &SM = STI.getSchedModel();
78  const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
79  for (WriteRef &WR : DependentWrites) {
80  WriteState &WS = *WR.getWriteState();
81  unsigned WriteResID = WS.getWriteResourceID();
82  int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
83  WS.addUser(&RS, ReadAdvance);
84  }
85 }
86 
87 Error DispatchStage::dispatch(InstRef IR) {
88  assert(!CarryOver && "Cannot dispatch another instruction!");
89  Instruction &IS = *IR.getInstruction();
90  const InstrDesc &Desc = IS.getDesc();
91  const unsigned NumMicroOps = Desc.NumMicroOps;
92  if (NumMicroOps > DispatchWidth) {
93  assert(AvailableEntries == DispatchWidth);
94  AvailableEntries = 0;
95  CarryOver = NumMicroOps - DispatchWidth;
96  CarriedOver = IR;
97  } else {
98  assert(AvailableEntries >= NumMicroOps);
99  AvailableEntries -= NumMicroOps;
100  }
101 
102  // Check if this instructions ends the dispatch group.
103  if (Desc.EndGroup)
104  AvailableEntries = 0;
105 
106  // Check if this is an optimizable reg-reg move.
107  bool IsEliminated = false;
108  if (IS.isOptimizableMove()) {
109  assert(IS.getDefs().size() == 1 && "Expected a single input!");
110  assert(IS.getUses().size() == 1 && "Expected a single output!");
111  IsEliminated = PRF.tryEliminateMove(IS.getDefs()[0], IS.getUses()[0]);
112  }
113 
114  // A dependency-breaking instruction doesn't have to wait on the register
115  // input operands, and it is often optimized at register renaming stage.
116  // Update RAW dependencies if this instruction is not a dependency-breaking
117  // instruction. A dependency-breaking instruction is a zero-latency
118  // instruction that doesn't consume hardware resources.
119  // An example of dependency-breaking instruction on X86 is a zero-idiom XOR.
120  //
121  // We also don't update data dependencies for instructions that have been
122  // eliminated at register renaming stage.
123  if (!IsEliminated) {
124  for (ReadState &RS : IS.getUses())
125  updateRAWDependencies(RS, STI);
126  }
127 
128  // By default, a dependency-breaking zero-idiom is expected to be optimized
129  // at register renaming stage. That means, no physical register is allocated
130  // to the instruction.
131  SmallVector<unsigned, 4> RegisterFiles(PRF.getNumRegisterFiles());
132  for (WriteState &WS : IS.getDefs())
133  PRF.addRegisterWrite(WriteRef(IR.getSourceIndex(), &WS), RegisterFiles);
134 
135  // Reserve slots in the RCU, and notify the instruction that it has been
136  // dispatched to the schedulers for execution.
137  IS.dispatch(RCU.reserveSlot(IR, NumMicroOps));
138 
139  // Notify listeners of the "instruction dispatched" event,
140  // and move IR to the next stage.
141  notifyInstructionDispatched(IR, RegisterFiles,
142  std::min(DispatchWidth, NumMicroOps));
143  return moveToTheNextStage(IR);
144 }
145 
147  PRF.cycleStart();
148 
149  if (!CarryOver) {
150  AvailableEntries = DispatchWidth;
151  return ErrorSuccess();
152  }
153 
154  AvailableEntries = CarryOver >= DispatchWidth ? 0 : DispatchWidth - CarryOver;
155  unsigned DispatchedOpcodes = DispatchWidth - AvailableEntries;
156  CarryOver -= DispatchedOpcodes;
157  assert(CarriedOver && "Invalid dispatched instruction");
158 
159  SmallVector<unsigned, 8> RegisterFiles(PRF.getNumRegisterFiles(), 0U);
160  notifyInstructionDispatched(CarriedOver, RegisterFiles, DispatchedOpcodes);
161  if (!CarryOver)
162  CarriedOver = InstRef();
163  return ErrorSuccess();
164 }
165 
166 bool DispatchStage::isAvailable(const InstRef &IR) const {
167  const InstrDesc &Desc = IR.getInstruction()->getDesc();
168  unsigned Required = std::min(Desc.NumMicroOps, DispatchWidth);
169  if (Required > AvailableEntries)
170  return false;
171 
172  if (Desc.BeginGroup && AvailableEntries != DispatchWidth)
173  return false;
174 
175  // The dispatch logic doesn't internally buffer instructions. It only accepts
176  // instructions that can be successfully moved to the next stage during this
177  // same cycle.
178  return canDispatch(IR);
179 }
180 
182  assert(canDispatch(IR) && "Cannot dispatch another instruction!");
183  return dispatch(IR);
184 }
185 
186 #ifndef NDEBUG
187 void DispatchStage::dump() const {
188  PRF.dump();
189  RCU.dump();
190 }
191 #endif
192 } // namespace mca
193 } // namespace llvm
Instruction * getInstruction()
Definition: Instruction.h:488
This class represents lattice values for constants.
Definition: AllocatorList.h:24
void addRegisterWrite(WriteRef Write, MutableArrayRef< unsigned > UsedPhysRegs)
Subclass of Error for the sole purpose of identifying the success path in the type system...
Definition: Error.h:325
unsigned getNumRegisterFiles() const
Definition: RegisterFile.h:226
bool checkNextStage(const InstRef &IR) const
Definition: Stage.h:63
An InstRef contains both a SourceMgr index and Instruction pair.
Definition: Instruction.h:478
Error cycleStart() override
Called once at the start of each cycle.
const InstrDesc & getDesc() const
Definition: Instruction.h:382
unsigned isAvailable(ArrayRef< unsigned > Regs) const
This file defines the main interface for hardware event listeners.
CHAIN = SC CHAIN, Imm128 - System call.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
Error moveToTheNextStage(InstRef &IR)
Called when an instruction is ready to move the next pipeline stage.
Definition: Stage.h:71
An instruction descriptor.
Definition: Instruction.h:322
This file models the dispatch component of an instruction pipeline.
bool isAvailable(unsigned Quantity=1) const
bool tryEliminateMove(WriteState &WS, ReadState &RS)
Error execute(InstRef &IR) override
The primary action that this stage performs on instruction IR.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void addRegisterRead(ReadState &RS, SmallVectorImpl< WriteRef > &Writes) const
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
A scheduler for Processor Resource Units and Processor Resource Groups.
#define LLVM_DEBUG(X)
Definition: Debug.h:123
unsigned reserveSlot(const InstRef &IS, unsigned NumMicroOps)
Statically lint checks LLVM IR
Definition: Lint.cpp:193
bool isAvailable(const InstRef &IR) const override
Returns true if it can execute IR during this cycle.