LLVM  14.0.0git
DispatchStage.cpp
Go to the documentation of this file.
1 //===--------------------- DispatchStage.cpp --------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 ///
10 /// This file models the dispatch component of an instruction pipeline.
11 ///
12 /// The DispatchStage is responsible for updating instruction dependencies
13 /// and communicating to the simulated instruction scheduler that an instruction
14 /// is ready to be scheduled for execution.
15 ///
16 //===----------------------------------------------------------------------===//
17 
21 #include "llvm/Support/Debug.h"
22 
23 #define DEBUG_TYPE "llvm-mca"
24 
25 namespace llvm {
26 namespace mca {
27 
29  const MCRegisterInfo &MRI,
30  unsigned MaxDispatchWidth, RetireControlUnit &R,
31  RegisterFile &F)
32  : DispatchWidth(MaxDispatchWidth), AvailableEntries(MaxDispatchWidth),
33  CarryOver(0U), CarriedOver(), STI(Subtarget), RCU(R), PRF(F) {
34  if (!DispatchWidth)
35  DispatchWidth = Subtarget.getSchedModel().IssueWidth;
36 }
37 
38 void DispatchStage::notifyInstructionDispatched(const InstRef &IR,
39  ArrayRef<unsigned> UsedRegs,
40  unsigned UOps) const {
41  LLVM_DEBUG(dbgs() << "[E] Instruction Dispatched: #" << IR << '\n');
42  notifyEvent<HWInstructionEvent>(
43  HWInstructionDispatchedEvent(IR, UsedRegs, UOps));
44 }
45 
46 bool DispatchStage::checkPRF(const InstRef &IR) const {
48  for (const WriteState &RegDef : IR.getInstruction()->getDefs())
49  RegDefs.emplace_back(RegDef.getRegisterID());
50 
51  const unsigned RegisterMask = PRF.isAvailable(RegDefs);
52  // A mask with all zeroes means: register files are available.
53  if (RegisterMask) {
54  notifyEvent<HWStallEvent>(
55  HWStallEvent(HWStallEvent::RegisterFileStall, IR));
56  return false;
57  }
58 
59  return true;
60 }
61 
62 bool DispatchStage::checkRCU(const InstRef &IR) const {
63  const unsigned NumMicroOps = IR.getInstruction()->getNumMicroOps();
64  if (RCU.isAvailable(NumMicroOps))
65  return true;
66  notifyEvent<HWStallEvent>(
68  return false;
69 }
70 
71 bool DispatchStage::canDispatch(const InstRef &IR) const {
72  bool CanDispatch = checkRCU(IR);
73  CanDispatch &= checkPRF(IR);
74  CanDispatch &= checkNextStage(IR);
75  return CanDispatch;
76 }
77 
78 Error DispatchStage::dispatch(InstRef IR) {
79  assert(!CarryOver && "Cannot dispatch another instruction!");
80  Instruction &IS = *IR.getInstruction();
81  const InstrDesc &Desc = IS.getDesc();
82  const unsigned NumMicroOps = IS.getNumMicroOps();
83  if (NumMicroOps > DispatchWidth) {
84  assert(AvailableEntries == DispatchWidth);
85  AvailableEntries = 0;
86  CarryOver = NumMicroOps - DispatchWidth;
87  CarriedOver = IR;
88  } else {
89  assert(AvailableEntries >= NumMicroOps);
90  AvailableEntries -= NumMicroOps;
91  }
92 
93  // Check if this instructions ends the dispatch group.
94  if (Desc.EndGroup)
95  AvailableEntries = 0;
96 
97  // Check if this is an optimizable reg-reg move or an XCHG-like instruction.
98  if (IS.isOptimizableMove())
99  if (PRF.tryEliminateMoveOrSwap(IS.getDefs(), IS.getUses()))
100  IS.setEliminated();
101 
102  // A dependency-breaking instruction doesn't have to wait on the register
103  // input operands, and it is often optimized at register renaming stage.
104  // Update RAW dependencies if this instruction is not a dependency-breaking
105  // instruction. A dependency-breaking instruction is a zero-latency
106  // instruction that doesn't consume hardware resources.
107  // An example of dependency-breaking instruction on X86 is a zero-idiom XOR.
108  //
109  // We also don't update data dependencies for instructions that have been
110  // eliminated at register renaming stage.
111  if (!IS.isEliminated()) {
112  for (ReadState &RS : IS.getUses())
113  PRF.addRegisterRead(RS, STI);
114  }
115 
116  // By default, a dependency-breaking zero-idiom is expected to be optimized
117  // at register renaming stage. That means, no physical register is allocated
118  // to the instruction.
119  SmallVector<unsigned, 4> RegisterFiles(PRF.getNumRegisterFiles());
120  for (WriteState &WS : IS.getDefs())
121  PRF.addRegisterWrite(WriteRef(IR.getSourceIndex(), &WS), RegisterFiles);
122 
123  // Reserve entries in the reorder buffer.
124  unsigned RCUTokenID = RCU.dispatch(IR);
125  // Notify the instruction that it has been dispatched.
126  IS.dispatch(RCUTokenID);
127 
128  // Notify listeners of the "instruction dispatched" event,
129  // and move IR to the next stage.
130  notifyInstructionDispatched(IR, RegisterFiles,
131  std::min(DispatchWidth, NumMicroOps));
132  return moveToTheNextStage(IR);
133 }
134 
136  // The retire stage is responsible for calling method `cycleStart`
137  // on the PRF.
138  if (!CarryOver) {
139  AvailableEntries = DispatchWidth;
140  return ErrorSuccess();
141  }
142 
143  AvailableEntries = CarryOver >= DispatchWidth ? 0 : DispatchWidth - CarryOver;
144  unsigned DispatchedOpcodes = DispatchWidth - AvailableEntries;
145  CarryOver -= DispatchedOpcodes;
146  assert(CarriedOver && "Invalid dispatched instruction");
147 
148  SmallVector<unsigned, 8> RegisterFiles(PRF.getNumRegisterFiles(), 0U);
149  notifyInstructionDispatched(CarriedOver, RegisterFiles, DispatchedOpcodes);
150  if (!CarryOver)
151  CarriedOver = InstRef();
152  return ErrorSuccess();
153 }
154 
156  // Conservatively bail out if there are no available dispatch entries.
157  if (!AvailableEntries)
158  return false;
159 
160  const Instruction &Inst = *IR.getInstruction();
161  unsigned NumMicroOps = Inst.getNumMicroOps();
162  const InstrDesc &Desc = Inst.getDesc();
163  unsigned Required = std::min(NumMicroOps, DispatchWidth);
164  if (Required > AvailableEntries)
165  return false;
166 
167  if (Desc.BeginGroup && AvailableEntries != DispatchWidth)
168  return false;
169 
170  // The dispatch logic doesn't internally buffer instructions. It only accepts
171  // instructions that can be successfully moved to the next stage during this
172  // same cycle.
173  return canDispatch(IR);
174 }
175 
177  assert(canDispatch(IR) && "Cannot dispatch another instruction!");
178  return dispatch(IR);
179 }
180 
181 #ifndef NDEBUG
182 void DispatchStage::dump() const {
183  PRF.dump();
184  RCU.dump();
185 }
186 #endif
187 } // namespace mca
188 } // namespace llvm
llvm::mca::DispatchStage::dump
void dump() const
Definition: DispatchStage.cpp:182
llvm::mca::DispatchStage::execute
Error execute(InstRef &IR) override
The primary action that this stage performs on instruction IR.
Definition: DispatchStage.cpp:176
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
llvm::lltok::Error
@ Error
Definition: LLToken.h:21
llvm::mca::RegisterFile::tryEliminateMoveOrSwap
bool tryEliminateMoveOrSwap(MutableArrayRef< WriteState > Writes, MutableArrayRef< ReadState > Reads)
Definition: RegisterFile.cpp:426
llvm::MCSubtargetInfo::getSchedModel
const MCSchedModel & getSchedModel() const
Get the machine model for this subtarget's CPU.
Definition: MCSubtargetInfo.h:162
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::mca::RetireControlUnit
This class tracks which instructions are in-flight (i.e., dispatched but not retired) in the OoO back...
Definition: RetireControlUnit.h:36
llvm::mca::HWStallEvent::RegisterFileStall
@ RegisterFileStall
Definition: HWEventListener.h:111
llvm::mca::Instruction
An instruction propagated through the simulated instruction pipeline.
Definition: Instruction.h:569
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
F
#define F(x, y, z)
Definition: MD5.cpp:56
DispatchStage.h
llvm::mca::RegisterFile::getNumRegisterFiles
unsigned getNumRegisterFiles() const
Definition: RegisterFile.h:293
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::mca::DispatchStage::DispatchStage
DispatchStage(const MCSubtargetInfo &Subtarget, const MCRegisterInfo &MRI, unsigned MaxDispatchWidth, RetireControlUnit &R, RegisterFile &F)
Definition: DispatchStage.cpp:28
llvm::mca::DispatchStage::cycleStart
Error cycleStart() override
Called once at the start of each cycle.
Definition: DispatchStage.cpp:135
llvm::mca::RegisterFile::isAvailable
unsigned isAvailable(ArrayRef< MCPhysReg > Regs) const
Definition: RegisterFile.cpp:660
llvm::mca::RetireControlUnit::dump
void dump() const
Definition: RetireControlUnit.cpp:96
llvm::cl::Required
@ Required
Definition: CommandLine.h:121
IR
Statically lint checks LLVM IR
Definition: Lint.cpp:744
llvm::mca::InstructionBase::getDesc
const InstrDesc & getDesc() const
Definition: Instruction.h:528
llvm::mca::InstrDesc
An instruction descriptor.
Definition: Instruction.h:447
llvm::mca::HWStallEvent::RetireControlUnitStall
@ RetireControlUnitStall
Definition: HWEventListener.h:112
llvm::MCSchedModel::IssueWidth
unsigned IssueWidth
Definition: MCSchedule.h:256
llvm::ErrorSuccess
Subclass of Error for the sole purpose of identifying the success path in the type system.
Definition: Error.h:329
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Scheduler.h
llvm::mca::RetireControlUnit::dispatch
unsigned dispatch(const InstRef &IS)
Definition: RetireControlUnit.cpp:43
llvm::mca::InstRef
An InstRef contains both a SourceMgr index and Instruction pair.
Definition: Instruction.h:686
llvm::mca::Stage::checkNextStage
bool checkNextStage(const InstRef &IR) const
Definition: Stage.h:62
llvm::mca::InstructionBase::getNumMicroOps
unsigned getNumMicroOps() const
Definition: Instruction.h:531
llvm::ArrayRef< unsigned >
llvm::min
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
Definition: FileCheck.cpp:357
llvm::MCRegisterInfo
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Definition: MCRegisterInfo.h:135
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::mca::RegisterFile::addRegisterRead
void addRegisterRead(ReadState &RS, const MCSubtargetInfo &STI) const
Definition: RegisterFile.cpp:618
llvm::mca::RegisterFile
Manages hardware register files, and tracks register definitions for register renaming purposes.
Definition: RegisterFile.h:83
HWEventListener.h
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::mca::RegisterFile::addRegisterWrite
void addRegisterWrite(WriteRef Write, MutableArrayRef< unsigned > UsedPhysRegs)
Definition: RegisterFile.cpp:228
llvm::ISD::RegisterMask
@ RegisterMask
Definition: ISDOpcodes.h:75
llvm::mca::Stage::moveToTheNextStage
Error moveToTheNextStage(InstRef &IR)
Called when an instruction is ready to move the next pipeline stage.
Definition: Stage.h:70
llvm::mca::InstrDesc::BeginGroup
unsigned BeginGroup
Definition: Instruction.h:478
llvm::mca::RetireControlUnit::isAvailable
bool isAvailable(unsigned Quantity=1) const
Definition: RetireControlUnit.h:84
llvm::mca::DispatchStage::isAvailable
bool isAvailable(const InstRef &IR) const override
Returns true if it can execute IR during this cycle.
Definition: DispatchStage.cpp:155
llvm::MCSubtargetInfo
Generic base class for all target subtargets.
Definition: MCSubtargetInfo.h:75
Debug.h
llvm::mca::RegisterFile::dump
void dump() const
Definition: RegisterFile.cpp:717
llvm::SmallVectorImpl::emplace_back
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:908
llvm::mca::HWInstructionDispatchedEvent
Definition: HWEventListener.h:73