LLVM  8.0.1
Instruction.cpp
Go to the documentation of this file.
1 //===--------------------- Instruction.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 //
10 // This file defines abstractions used by the Pipeline to model register reads,
11 // register writes and instructions.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/MCA/Instruction.h"
16 #include "llvm/Support/Debug.h"
18 
19 namespace llvm {
20 namespace mca {
21 
22 void ReadState::writeStartEvent(unsigned Cycles) {
23  assert(DependentWrites);
24  assert(CyclesLeft == UNKNOWN_CYCLES);
25 
26  // This read may be dependent on more than one write. This typically occurs
27  // when a definition is the result of multiple writes where at least one
28  // write does a partial register update.
29  // The HW is forced to do some extra bookkeeping to track of all the
30  // dependent writes, and implement a merging scheme for the partial writes.
31  --DependentWrites;
32  TotalCycles = std::max(TotalCycles, Cycles);
33 
34  if (!DependentWrites) {
35  CyclesLeft = TotalCycles;
36  IsReady = !CyclesLeft;
37  }
38 }
39 
41  assert(CyclesLeft == UNKNOWN_CYCLES);
42  // Update the number of cycles left based on the WriteDescriptor info.
43  CyclesLeft = getLatency();
44 
45  // Now that the time left before write-back is known, notify
46  // all the users.
47  for (const std::pair<ReadState *, int> &User : Users) {
48  ReadState *RS = User.first;
49  unsigned ReadCycles = std::max(0, CyclesLeft - User.second);
50  RS->writeStartEvent(ReadCycles);
51  }
52 
53  // Notify any writes that are in a false dependency with this write.
54  if (PartialWrite)
55  PartialWrite->writeStartEvent(CyclesLeft);
56 }
57 
58 void WriteState::addUser(ReadState *User, int ReadAdvance) {
59  // If CyclesLeft is different than -1, then we don't need to
60  // update the list of users. We can just notify the user with
61  // the actual number of cycles left (which may be zero).
62  if (CyclesLeft != UNKNOWN_CYCLES) {
63  unsigned ReadCycles = std::max(0, CyclesLeft - ReadAdvance);
64  User->writeStartEvent(ReadCycles);
65  return;
66  }
67 
68  if (llvm::find_if(Users, [&User](const std::pair<ReadState *, int> &Use) {
69  return Use.first == User;
70  }) == Users.end()) {
71  Users.emplace_back(User, ReadAdvance);
72  }
73 }
74 
76  if (CyclesLeft != UNKNOWN_CYCLES) {
77  User->writeStartEvent(std::max(0, CyclesLeft));
78  return;
79  }
80 
81  assert(!PartialWrite && "PartialWrite already set!");
82  PartialWrite = User;
83  User->setDependentWrite(this);
84 }
85 
87  // Note: CyclesLeft can be a negative number. It is an error to
88  // make it an unsigned quantity because users of this write may
89  // specify a negative ReadAdvance.
90  if (CyclesLeft != UNKNOWN_CYCLES)
91  CyclesLeft--;
92 
93  if (DependentWriteCyclesLeft)
94  DependentWriteCyclesLeft--;
95 }
96 
98  // Update the total number of cycles.
99  if (DependentWrites && TotalCycles) {
100  --TotalCycles;
101  return;
102  }
103 
104  // Bail out immediately if we don't know how many cycles are left.
105  if (CyclesLeft == UNKNOWN_CYCLES)
106  return;
107 
108  if (CyclesLeft) {
109  --CyclesLeft;
110  IsReady = !CyclesLeft;
111  }
112 }
113 
114 #ifndef NDEBUG
115 void WriteState::dump() const {
116  dbgs() << "{ OpIdx=" << WD->OpIndex << ", Lat=" << getLatency() << ", RegID "
117  << getRegisterID() << ", Cycles Left=" << getCyclesLeft() << " }";
118 }
119 
120 void WriteRef::dump() const {
121  dbgs() << "IID=" << getSourceIndex() << ' ';
122  if (isValid())
123  getWriteState()->dump();
124  else
125  dbgs() << "(null)";
126 }
127 #endif
128 
129 void Instruction::dispatch(unsigned RCUToken) {
130  assert(Stage == IS_INVALID);
131  Stage = IS_AVAILABLE;
132  RCUTokenID = RCUToken;
133 
134  // Check if input operands are already available.
135  update();
136 }
137 
139  assert(Stage == IS_READY);
140  Stage = IS_EXECUTING;
141 
142  // Set the cycles left before the write-back stage.
143  CyclesLeft = getLatency();
144 
145  for (WriteState &WS : getDefs())
146  WS.onInstructionIssued();
147 
148  // Transition to the "executed" stage if this is a zero-latency instruction.
149  if (!CyclesLeft)
150  Stage = IS_EXECUTED;
151 }
152 
154  assert(Stage == IS_READY && "Invalid internal state!");
155  CyclesLeft = 0;
156  Stage = IS_EXECUTED;
157 }
158 
160  assert(isDispatched() && "Unexpected instruction stage found!");
161 
162  if (!all_of(getUses(), [](const ReadState &Use) { return Use.isReady(); }))
163  return;
164 
165  // A partial register write cannot complete before a dependent write.
166  auto IsDefReady = [&](const WriteState &Def) {
167  if (!Def.getDependentWrite()) {
168  unsigned CyclesLeft = Def.getDependentWriteCyclesLeft();
169  return !CyclesLeft || CyclesLeft < getLatency();
170  }
171  return false;
172  };
173 
174  if (all_of(getDefs(), IsDefReady))
175  Stage = IS_READY;
176 }
177 
179  if (isReady())
180  return;
181 
182  if (isDispatched()) {
183  for (ReadState &Use : getUses())
184  Use.cycleEvent();
185 
186  for (WriteState &Def : getDefs())
187  Def.cycleEvent();
188 
189  update();
190  return;
191  }
192 
193  assert(isExecuting() && "Instruction not in-flight?");
194  assert(CyclesLeft && "Instruction already executed?");
195  for (WriteState &Def : getDefs())
196  Def.cycleEvent();
197  CyclesLeft--;
198  if (!CyclesLeft)
199  Stage = IS_EXECUTED;
200 }
201 
202 const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();
203 
204 } // namespace mca
205 } // namespace llvm
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
This class represents lattice values for constants.
Definition: AllocatorList.h:24
constexpr int UNKNOWN_CYCLES
Definition: Instruction.h:34
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1186
iv Induction Variable Users
Definition: IVUsers.cpp:52
void setDependentWrite(WriteState *Other)
Definition: Instruction.h:177
Tracks register operand latency in cycles.
Definition: Instruction.h:205
A Use represents the edge between a Value definition and its users.
Definition: Use.h:56
static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst)
Gets latency information for Inst, based on DC information.
void writeStartEvent(unsigned Cycles)
Definition: Instruction.cpp:22
bool isReady() const
Definition: Instruction.h:243
auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1214
void dispatch(unsigned RCUTokenID)
void addUser(ReadState *Use, int ReadAdvance)
Definition: Instruction.cpp:58
Tracks uses of a register definition (e.g.
Definition: Instruction.h:90
void writeStartEvent(unsigned Cycles)
Definition: Instruction.h:178
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
This file defines abstractions used by the Pipeline to model register reads, register writes and inst...
unsigned getRegisterID() const
Definition: Instruction.h:240
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())