blob: 057e95ca9990fdf967cda1c741c5e8e2ce453db7 [file] [log] [blame]
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +00001//===--------------------- 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//
Matt Davisd8c387b2018-06-25 16:53:00 +000010// This file defines abstractions used by the Pipeline to model register reads,
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000011// register writes and instructions.
12//
13//===----------------------------------------------------------------------===//
14
Clement Courbet8178ac82018-12-17 08:08:31 +000015#include "llvm/MCA/Instruction.h"
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000016#include "llvm/Support/Debug.h"
17#include "llvm/Support/raw_ostream.h"
18
Fangrui Song467c3072018-10-30 15:56:08 +000019namespace llvm {
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000020namespace mca {
21
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000022void 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
Andrea Di Biagio0093dbb2018-06-27 11:17:07 +000034 if (!DependentWrites) {
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000035 CyclesLeft = TotalCycles;
Andrea Di Biagio0093dbb2018-06-27 11:17:07 +000036 IsReady = !CyclesLeft;
37 }
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000038}
39
40void WriteState::onInstructionIssued() {
41 assert(CyclesLeft == UNKNOWN_CYCLES);
42 // Update the number of cycles left based on the WriteDescriptor info.
Andrea Di Biagio2d706a62018-07-06 13:46:10 +000043 CyclesLeft = getLatency();
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000044
Andrea Di Biagio04b507e2018-06-05 17:12:02 +000045 // Now that the time left before write-back is known, notify
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000046 // 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 }
Andrea Di Biagioab518ce2018-11-22 12:48:57 +000052
53 // Notify any writes that are in a false dependency with this write.
54 if (PartialWrite)
55 PartialWrite->writeStartEvent(CyclesLeft);
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000056}
57
58void 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
Andrea Di Biagiofb147de2018-11-22 14:48:53 +000068 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 }
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000073}
74
Andrea Di Biagioab518ce2018-11-22 12:48:57 +000075void WriteState::addUser(WriteState *User) {
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
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000086void WriteState::cycleEvent() {
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--;
Andrea Di Biagioab518ce2018-11-22 12:48:57 +000092
93 if (DependentWriteCyclesLeft)
94 DependentWriteCyclesLeft--;
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +000095}
96
97void ReadState::cycleEvent() {
Andrea Di Biagio04b507e2018-06-05 17:12:02 +000098 // 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.
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +0000105 if (CyclesLeft == UNKNOWN_CYCLES)
106 return;
107
Andrea Di Biagio0093dbb2018-06-27 11:17:07 +0000108 if (CyclesLeft) {
Andrea Di Biagio04b507e2018-06-05 17:12:02 +0000109 --CyclesLeft;
Andrea Di Biagio0093dbb2018-06-27 11:17:07 +0000110 IsReady = !CyclesLeft;
111 }
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +0000112}
113
114#ifndef NDEBUG
115void WriteState::dump() const {
Andrea Di Biagioee5a5142018-10-29 13:29:22 +0000116 dbgs() << "{ OpIdx=" << WD->OpIndex << ", Lat=" << getLatency() << ", RegID "
Andrea Di Biagio92712652018-07-05 16:13:49 +0000117 << getRegisterID() << ", Cycles Left=" << getCyclesLeft() << " }";
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +0000118}
Andrea Di Biagioa2237ff2018-06-28 15:50:26 +0000119
120void WriteRef::dump() const {
Andrea Di Biagio92712652018-07-05 16:13:49 +0000121 dbgs() << "IID=" << getSourceIndex() << ' ';
Andrea Di Biagioa2237ff2018-06-28 15:50:26 +0000122 if (isValid())
123 getWriteState()->dump();
124 else
125 dbgs() << "(null)";
126}
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +0000127#endif
128
Andrea Di Biagioefac2a82018-03-22 11:39:34 +0000129void Instruction::dispatch(unsigned RCUToken) {
Andrea Di Biagio280f00a2018-03-22 10:19:20 +0000130 assert(Stage == IS_INVALID);
131 Stage = IS_AVAILABLE;
Andrea Di Biagioefac2a82018-03-22 11:39:34 +0000132 RCUTokenID = RCUToken;
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +0000133
Andrea Di Biagioefac2a82018-03-22 11:39:34 +0000134 // Check if input operands are already available.
Andrea Di Biagio8ff27db2018-03-29 14:26:56 +0000135 update();
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +0000136}
137
138void Instruction::execute() {
139 assert(Stage == IS_READY);
140 Stage = IS_EXECUTING;
Andrea Di Biagioefac2a82018-03-22 11:39:34 +0000141
142 // Set the cycles left before the write-back stage.
Andrea Di Biagioa64e4ae2018-10-25 17:03:51 +0000143 CyclesLeft = getLatency();
Andrea Di Biagioefac2a82018-03-22 11:39:34 +0000144
Andrea Di Biagioa64e4ae2018-10-25 17:03:51 +0000145 for (WriteState &WS : getDefs())
146 WS.onInstructionIssued();
Andrea Di Biagioefac2a82018-03-22 11:39:34 +0000147
148 // Transition to the "executed" stage if this is a zero-latency instruction.
Andrea Di Biagio280f00a2018-03-22 10:19:20 +0000149 if (!CyclesLeft)
150 Stage = IS_EXECUTED;
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +0000151}
152
Andrea Di Biagio97666c42018-10-03 15:02:44 +0000153void Instruction::forceExecuted() {
154 assert(Stage == IS_READY && "Invalid internal state!");
155 CyclesLeft = 0;
156 Stage = IS_EXECUTED;
157}
158
Andrea Di Biagio8ff27db2018-03-29 14:26:56 +0000159void Instruction::update() {
Andrea Di Biagio0093dbb2018-06-27 11:17:07 +0000160 assert(isDispatched() && "Unexpected instruction stage found!");
Andrea Di Biagioeaabc712018-07-15 11:01:38 +0000161
Andrea Di Biagioa64e4ae2018-10-25 17:03:51 +0000162 if (!all_of(getUses(), [](const ReadState &Use) { return Use.isReady(); }))
Andrea Di Biagioeaabc712018-07-15 11:01:38 +0000163 return;
164
165 // A partial register write cannot complete before a dependent write.
Andrea Di Biagioa64e4ae2018-10-25 17:03:51 +0000166 auto IsDefReady = [&](const WriteState &Def) {
Andrea Di Biagioab518ce2018-11-22 12:48:57 +0000167 if (!Def.getDependentWrite()) {
168 unsigned CyclesLeft = Def.getDependentWriteCyclesLeft();
169 return !CyclesLeft || CyclesLeft < getLatency();
Andrea Di Biagioeaabc712018-07-15 11:01:38 +0000170 }
Andrea Di Biagioab518ce2018-11-22 12:48:57 +0000171 return false;
Andrea Di Biagioeaabc712018-07-15 11:01:38 +0000172 };
173
Andrea Di Biagioa64e4ae2018-10-25 17:03:51 +0000174 if (all_of(getDefs(), IsDefReady))
Andrea Di Biagio8ff27db2018-03-29 14:26:56 +0000175 Stage = IS_READY;
176}
177
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +0000178void Instruction::cycleEvent() {
Andrea Di Biagio280f00a2018-03-22 10:19:20 +0000179 if (isReady())
180 return;
181
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +0000182 if (isDispatched()) {
Andrea Di Biagioa64e4ae2018-10-25 17:03:51 +0000183 for (ReadState &Use : getUses())
184 Use.cycleEvent();
Andrea Di Biagio0093dbb2018-06-27 11:17:07 +0000185
Andrea Di Biagioab518ce2018-11-22 12:48:57 +0000186 for (WriteState &Def : getDefs())
187 Def.cycleEvent();
188
Andrea Di Biagioeaabc712018-07-15 11:01:38 +0000189 update();
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +0000190 return;
191 }
Andrea Di Biagio280f00a2018-03-22 10:19:20 +0000192
193 assert(isExecuting() && "Instruction not in-flight?");
194 assert(CyclesLeft && "Instruction already executed?");
Andrea Di Biagioa64e4ae2018-10-25 17:03:51 +0000195 for (WriteState &Def : getDefs())
196 Def.cycleEvent();
Andrea Di Biagio280f00a2018-03-22 10:19:20 +0000197 CyclesLeft--;
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +0000198 if (!CyclesLeft)
199 Stage = IS_EXECUTED;
200}
Andrea Di Biagioa2237ff2018-06-28 15:50:26 +0000201
202const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();
203
Andrea Di Biagio29b29cc2018-03-08 13:05:02 +0000204} // namespace mca
Fangrui Song467c3072018-10-30 15:56:08 +0000205} // namespace llvm