blob: f84c7811138670cf6d2e61e526954cf374774674 [file] [log] [blame]
Andrea Di Biagio3a6b0922018-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 Davisdea343d2018-06-25 16:53:00 +000010// This file defines abstractions used by the Pipeline to model register reads,
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000011// register writes and instructions.
12//
13//===----------------------------------------------------------------------===//
14
15#include "Instruction.h"
16#include "llvm/Support/Debug.h"
17#include "llvm/Support/raw_ostream.h"
18
19namespace mca {
20
21using namespace llvm;
22
23void ReadState::writeStartEvent(unsigned Cycles) {
24 assert(DependentWrites);
25 assert(CyclesLeft == UNKNOWN_CYCLES);
26
27 // This read may be dependent on more than one write. This typically occurs
28 // when a definition is the result of multiple writes where at least one
29 // write does a partial register update.
30 // The HW is forced to do some extra bookkeeping to track of all the
31 // dependent writes, and implement a merging scheme for the partial writes.
32 --DependentWrites;
33 TotalCycles = std::max(TotalCycles, Cycles);
34
Andrea Di Biagioeb1bef62018-06-27 11:17:07 +000035 if (!DependentWrites) {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000036 CyclesLeft = TotalCycles;
Andrea Di Biagioeb1bef62018-06-27 11:17:07 +000037 IsReady = !CyclesLeft;
38 }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000039}
40
41void WriteState::onInstructionIssued() {
42 assert(CyclesLeft == UNKNOWN_CYCLES);
43 // Update the number of cycles left based on the WriteDescriptor info.
44 CyclesLeft = WD.Latency;
45
Andrea Di Biagio757600b2018-06-05 17:12:02 +000046 // Now that the time left before write-back is known, notify
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000047 // all the users.
48 for (const std::pair<ReadState *, int> &User : Users) {
49 ReadState *RS = User.first;
50 unsigned ReadCycles = std::max(0, CyclesLeft - User.second);
51 RS->writeStartEvent(ReadCycles);
52 }
53}
54
55void WriteState::addUser(ReadState *User, int ReadAdvance) {
56 // If CyclesLeft is different than -1, then we don't need to
57 // update the list of users. We can just notify the user with
58 // the actual number of cycles left (which may be zero).
59 if (CyclesLeft != UNKNOWN_CYCLES) {
60 unsigned ReadCycles = std::max(0, CyclesLeft - ReadAdvance);
61 User->writeStartEvent(ReadCycles);
62 return;
63 }
64
65 std::pair<ReadState *, int> NewPair(User, ReadAdvance);
66 Users.insert(NewPair);
67}
68
69void WriteState::cycleEvent() {
70 // Note: CyclesLeft can be a negative number. It is an error to
71 // make it an unsigned quantity because users of this write may
72 // specify a negative ReadAdvance.
73 if (CyclesLeft != UNKNOWN_CYCLES)
74 CyclesLeft--;
75}
76
77void ReadState::cycleEvent() {
Andrea Di Biagio757600b2018-06-05 17:12:02 +000078 // Update the total number of cycles.
79 if (DependentWrites && TotalCycles) {
80 --TotalCycles;
81 return;
82 }
83
84 // Bail out immediately if we don't know how many cycles are left.
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000085 if (CyclesLeft == UNKNOWN_CYCLES)
86 return;
87
Andrea Di Biagioeb1bef62018-06-27 11:17:07 +000088 if (CyclesLeft) {
Andrea Di Biagio757600b2018-06-05 17:12:02 +000089 --CyclesLeft;
Andrea Di Biagioeb1bef62018-06-27 11:17:07 +000090 IsReady = !CyclesLeft;
91 }
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000092}
93
94#ifndef NDEBUG
95void WriteState::dump() const {
96 dbgs() << "{ OpIdx=" << WD.OpIndex << ", Lat=" << WD.Latency << ", RegID "
97 << getRegisterID() << ", Cycles Left=" << getCyclesLeft() << " }\n";
98}
99#endif
100
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000101void Instruction::dispatch(unsigned RCUToken) {
Andrea Di Biagio35622482018-03-22 10:19:20 +0000102 assert(Stage == IS_INVALID);
103 Stage = IS_AVAILABLE;
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000104 RCUTokenID = RCUToken;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000105
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000106 // Check if input operands are already available.
Andrea Di Biagio0a837ef2018-03-29 14:26:56 +0000107 update();
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000108}
109
110void Instruction::execute() {
111 assert(Stage == IS_READY);
112 Stage = IS_EXECUTING;
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000113
114 // Set the cycles left before the write-back stage.
Andrea Di Biagio2dee62b2018-03-22 14:14:49 +0000115 CyclesLeft = Desc.MaxLatency;
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000116
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000117 for (UniqueDef &Def : Defs)
118 Def->onInstructionIssued();
Andrea Di Biagio09ea09e2018-03-22 11:39:34 +0000119
120 // Transition to the "executed" stage if this is a zero-latency instruction.
Andrea Di Biagio35622482018-03-22 10:19:20 +0000121 if (!CyclesLeft)
122 Stage = IS_EXECUTED;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000123}
124
Andrea Di Biagio0a837ef2018-03-29 14:26:56 +0000125void Instruction::update() {
Andrea Di Biagioeb1bef62018-06-27 11:17:07 +0000126 assert(isDispatched() && "Unexpected instruction stage found!");
Andrea Di Biagio0a837ef2018-03-29 14:26:56 +0000127 if (llvm::all_of(Uses, [](const UniqueUse &Use) { return Use->isReady(); }))
128 Stage = IS_READY;
129}
130
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000131void Instruction::cycleEvent() {
Andrea Di Biagio35622482018-03-22 10:19:20 +0000132 if (isReady())
133 return;
134
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000135 if (isDispatched()) {
Andrea Di Biagioeb1bef62018-06-27 11:17:07 +0000136 bool IsReady = true;
137 for (UniqueUse &Use : Uses) {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000138 Use->cycleEvent();
Andrea Di Biagioeb1bef62018-06-27 11:17:07 +0000139 IsReady &= Use->isReady();
140 }
141
142 if (IsReady)
143 Stage = IS_READY;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000144 return;
145 }
Andrea Di Biagio35622482018-03-22 10:19:20 +0000146
147 assert(isExecuting() && "Instruction not in-flight?");
148 assert(CyclesLeft && "Instruction already executed?");
149 for (UniqueDef &Def : Defs)
150 Def->cycleEvent();
151 CyclesLeft--;
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000152 if (!CyclesLeft)
153 Stage = IS_EXECUTED;
154}
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +0000155} // namespace mca