blob: 74b98f1b7ab184ec79eda0a09310adf0cc0bcc89 [file] [log] [blame]
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +00001//===----------------------- Dispatch.h -------------------------*- 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 classes that are used to model register files,
12/// reorder buffers and the hardware dispatch logic.
13///
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_TOOLS_LLVM_MCA_DISPATCH_H
17#define LLVM_TOOLS_LLVM_MCA_DISPATCH_H
18
19#include "Instruction.h"
Matt Davis6aa5dcd2018-05-01 23:04:01 +000020#include "RetireControlUnit.h"
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000021#include "llvm/MC/MCRegisterInfo.h"
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +000022#include "llvm/MC/MCSubtargetInfo.h"
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000023#include <map>
24
25namespace mca {
26
27class WriteState;
28class DispatchUnit;
29class Scheduler;
30class Backend;
31
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000032/// Manages hardware register files, and tracks data dependencies
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +000033/// between registers.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000034class RegisterFile {
35 const llvm::MCRegisterInfo &MRI;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000036
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +000037 // Each register file is described by an instance of RegisterMappingTracker.
38 // RegisterMappingTracker tracks the number of register mappings dynamically
39 // allocated during the execution.
40 struct RegisterMappingTracker {
41 // Total number of register mappings that are available for register
42 // renaming. A value of zero for this field means: this register file has
43 // an unbounded number of registers.
44 const unsigned TotalMappings;
45 // Number of mappings that are currently in use.
46 unsigned NumUsedMappings;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000047
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +000048 RegisterMappingTracker(unsigned NumMappings)
Andrea Di Biagio12ef5262018-03-21 18:11:05 +000049 : TotalMappings(NumMappings), NumUsedMappings(0) {}
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +000050 };
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000051
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +000052 // This is where information related to the various register files is kept.
53 // This set always contains at least one register file at index #0. That
54 // register file "sees" all the physical registers declared by the target, and
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +000055 // (by default) it allows an unbounded number of mappings.
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +000056 // Users can limit the number of mappings that can be created by register file
57 // #0 through the command line flag `-register-file-size`.
58 llvm::SmallVector<RegisterMappingTracker, 4> RegisterFiles;
59
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +000060 // This pair is used to identify the owner of a physical register, as well as
61 // the cost of using that register file.
62 using IndexPlusCostPairTy = std::pair<unsigned, unsigned>;
63
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +000064 // RegisterMapping objects are mainly used to track physical register
65 // definitions. A WriteState object describes a register definition, and it is
66 // used to track RAW dependencies (see Instruction.h). A RegisterMapping
67 // object also specifies the set of register files. The mapping between
68 // physreg and register files is done using a "register file mask".
69 //
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +000070 // A register file index identifies a user defined register file.
71 // There is one index per RegisterMappingTracker, and index #0 is reserved to
72 // the default unified register file.
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +000073 //
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +000074 // This implementation does not allow overlapping register files. The only
75 // register file that is allowed to overlap with other register files is
76 // register file #0.
77 using RegisterMapping = std::pair<WriteState *, IndexPlusCostPairTy>;
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +000078
79 // This map contains one entry for each physical register defined by the
80 // processor scheduling model.
81 std::vector<RegisterMapping> RegisterMappings;
82
83 // This method creates a new RegisterMappingTracker for a register file that
84 // contains all the physical registers specified by the register classes in
85 // the 'RegisterClasses' set.
86 //
87 // The long term goal is to let scheduling models optionally describe register
88 // files via tablegen definitions. This is still a work in progress.
89 // For example, here is how a tablegen definition for a x86 FP register file
90 // that features AVX might look like:
91 //
92 // def FPRegisterFile : RegisterFile<[VR128RegClass, VR256RegClass], 60>
93 //
94 // Here FPRegisterFile contains all the registers defined by register class
95 // VR128RegClass and VR256RegClass. FPRegisterFile implements 60
96 // registers which can be used for register renaming purpose.
97 //
98 // The list of register classes is then converted by the tablegen backend into
99 // a list of register class indices. That list, along with the number of
100 // available mappings, is then used to create a new RegisterMappingTracker.
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000101 void
102 addRegisterFile(llvm::ArrayRef<llvm::MCRegisterCostEntry> RegisterClasses,
103 unsigned NumPhysRegs);
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000104
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000105 // Allocates register mappings in register file specified by the
106 // IndexPlusCostPairTy object. This method is called from addRegisterMapping.
Andrea Di Biagio8ea3a342018-05-14 15:08:22 +0000107 void allocatePhysRegs(IndexPlusCostPairTy IPC,
108 llvm::MutableArrayRef<unsigned> UsedPhysRegs);
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000109
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000110 // Removes a previously allocated mapping from the register file referenced
111 // by the IndexPlusCostPairTy object. This method is called from
112 // invalidateRegisterMapping.
Andrea Di Biagio8ea3a342018-05-14 15:08:22 +0000113 void freePhysRegs(IndexPlusCostPairTy IPC,
114 llvm::MutableArrayRef<unsigned> FreedPhysRegs);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000115
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000116 // Create an instance of RegisterMappingTracker for every register file
117 // specified by the processor model.
118 // If no register file is specified, then this method creates a single
119 // register file with an unbounded number of registers.
120 void initialize(const llvm::MCSchedModel &SM, unsigned NumRegs);
121
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000122public:
Andrea Di Biagio9da4d6d2018-04-03 13:36:24 +0000123 RegisterFile(const llvm::MCSchedModel &SM, const llvm::MCRegisterInfo &mri,
124 unsigned NumRegs = 0)
125 : MRI(mri), RegisterMappings(mri.getNumRegs(), {nullptr, {0, 0}}) {
126 initialize(SM, NumRegs);
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000127 }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000128
Andrea Di Biagio8ea3a342018-05-14 15:08:22 +0000129 // This method updates the data dependency graph by inserting a new register
130 // definition. This method is also responsible for updating the number of used
131 // physical registers in the register file(s). The number of physical
132 // registers is updated only if flag ShouldAllocatePhysRegs is set.
133 void addRegisterWrite(WriteState &WS,
134 llvm::MutableArrayRef<unsigned> UsedPhysRegs,
135 bool ShouldAllocatePhysRegs = true);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000136
Andrea Di Biagio8ea3a342018-05-14 15:08:22 +0000137 // Updates the data dependency graph by removing a write. It also updates the
138 // internal state of the register file(s) by freeing physical registers.
139 // The number of physical registers is updated only if flag ShouldFreePhysRegs
140 // is set.
141 void removeRegisterWrite(const WriteState &WS,
142 llvm::MutableArrayRef<unsigned> FreedPhysRegs,
143 bool ShouldFreePhysRegs = true);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000144
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000145 // Checks if there are enough microarchitectural registers in the register
146 // files. Returns a "response mask" where each bit is the response from a
147 // RegisterMappingTracker.
148 // For example: if all register files are available, then the response mask
149 // is a bitmask of all zeroes. If Instead register file #1 is not available,
150 // then the response mask is 0b10.
Andrea Di Biagio847accd2018-03-20 19:06:34 +0000151 unsigned isAvailable(llvm::ArrayRef<unsigned> Regs) const;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000152 void collectWrites(llvm::SmallVectorImpl<WriteState *> &Writes,
153 unsigned RegID) const;
154 void updateOnRead(ReadState &RS, unsigned RegID);
Andrea Di Biagio12ef5262018-03-21 18:11:05 +0000155
Andrea Di Biagioe64f3b12018-03-18 15:33:27 +0000156 unsigned getNumRegisterFiles() const { return RegisterFiles.size(); }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000157
158#ifndef NDEBUG
159 void dump() const;
160#endif
161};
162
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000163// Implements the hardware dispatch logic.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000164//
165// This class is responsible for the dispatch stage, in which instructions are
166// dispatched in groups to the Scheduler. An instruction can be dispatched if
167// functional units are available.
168// To be more specific, an instruction can be dispatched to the Scheduler if:
169// 1) There are enough entries in the reorder buffer (implemented by class
170// RetireControlUnit) to accomodate all opcodes.
171// 2) There are enough temporaries to rename output register operands.
172// 3) There are enough entries available in the used buffered resource(s).
173//
174// The number of micro opcodes that can be dispatched in one cycle is limited by
175// the value of field 'DispatchWidth'. A "dynamic dispatch stall" occurs when
176// processor resources are not available (i.e. at least one of the
177// abovementioned checks fails). Dispatch stall events are counted during the
178// entire execution of the code, and displayed by the performance report when
179// flag '-verbose' is specified.
180//
181// If the number of micro opcodes of an instruction is bigger than
182// DispatchWidth, then it can only be dispatched at the beginning of one cycle.
183// The DispatchUnit will still have to wait for a number of cycles (depending on
184// the DispatchWidth and the number of micro opcodes) before it can serve other
185// instructions.
186class DispatchUnit {
187 unsigned DispatchWidth;
188 unsigned AvailableEntries;
189 unsigned CarryOver;
190 Scheduler *SC;
191
192 std::unique_ptr<RegisterFile> RAT;
193 std::unique_ptr<RetireControlUnit> RCU;
194 Backend *Owner;
195
Matt Davis21a8d322018-05-07 18:29:15 +0000196 bool checkRAT(const InstRef &IR);
197 bool checkRCU(const InstRef &IR);
198 bool checkScheduler(const InstRef &IR);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000199
Andrea Di Biagio4732d43ca2018-03-14 14:57:23 +0000200 void updateRAWDependencies(ReadState &RS, const llvm::MCSubtargetInfo &STI);
Matt Davis21a8d322018-05-07 18:29:15 +0000201 void notifyInstructionDispatched(const InstRef &IR,
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000202 llvm::ArrayRef<unsigned> UsedPhysRegs);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000203
204public:
Andrea Di Biagioc74ad502018-04-05 15:41:41 +0000205 DispatchUnit(Backend *B, const llvm::MCSchedModel &SM,
206 const llvm::MCRegisterInfo &MRI, unsigned RegisterFileSize,
207 unsigned MaxDispatchWidth, Scheduler *Sched)
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000208 : DispatchWidth(MaxDispatchWidth), AvailableEntries(MaxDispatchWidth),
209 CarryOver(0U), SC(Sched),
Andrea Di Biagioc74ad502018-04-05 15:41:41 +0000210 RAT(llvm::make_unique<RegisterFile>(SM, MRI, RegisterFileSize)),
211 RCU(llvm::make_unique<RetireControlUnit>(SM, this)), Owner(B) {}
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000212
213 unsigned getDispatchWidth() const { return DispatchWidth; }
214
215 bool isAvailable(unsigned NumEntries) const {
216 return NumEntries <= AvailableEntries || AvailableEntries == DispatchWidth;
217 }
218
219 bool isRCUEmpty() const { return RCU->isEmpty(); }
220
Matt Davis21a8d322018-05-07 18:29:15 +0000221 bool canDispatch(const InstRef &IR) {
222 assert(isAvailable(IR.getInstruction()->getDesc().NumMicroOps));
223 return checkRCU(IR) && checkRAT(IR) && checkScheduler(IR);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000224 }
225
Matt Davis21a8d322018-05-07 18:29:15 +0000226 void dispatch(InstRef IR, const llvm::MCSubtargetInfo &STI);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000227
228 void collectWrites(llvm::SmallVectorImpl<WriteState *> &Vec,
229 unsigned RegID) const {
230 return RAT->collectWrites(Vec, RegID);
231 }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000232
Andrea Di Biagio3e646442018-04-12 10:49:40 +0000233 void cycleEvent() {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000234 RCU->cycleEvent();
235 AvailableEntries =
236 CarryOver >= DispatchWidth ? 0 : DispatchWidth - CarryOver;
237 CarryOver = CarryOver >= DispatchWidth ? CarryOver - DispatchWidth : 0U;
238 }
239
Matt Davis21a8d322018-05-07 18:29:15 +0000240 void notifyInstructionRetired(const InstRef &IR);
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000241
Matt Davis21a8d322018-05-07 18:29:15 +0000242 void notifyDispatchStall(const InstRef &IR, unsigned EventType);
Andrea Di Biagio91ab2ee2018-03-19 13:23:07 +0000243
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000244 void onInstructionExecuted(unsigned TokenID) {
245 RCU->onInstructionExecuted(TokenID);
246 }
247
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000248#ifndef NDEBUG
249 void dump() const;
250#endif
251};
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000252} // namespace mca
253
254#endif