1 //===--------------------- Instruction.cpp ----------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines abstractions used by the Pipeline to model register reads,
11 // register writes and instructions.
13 //===----------------------------------------------------------------------===//
15 #include "Instruction.h"
16 #include "llvm/Support/Debug.h"
17 #include "llvm/Support/raw_ostream.h"
23 void ReadState::writeStartEvent(unsigned Cycles) {
24 assert(DependentWrites);
25 assert(CyclesLeft == UNKNOWN_CYCLES);
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.
33 TotalCycles = std::max(TotalCycles, Cycles);
35 if (!DependentWrites) {
36 CyclesLeft = TotalCycles;
37 IsReady = !CyclesLeft;
41 void WriteState::onInstructionIssued() {
42 assert(CyclesLeft == UNKNOWN_CYCLES);
43 // Update the number of cycles left based on the WriteDescriptor info.
44 CyclesLeft = getLatency();
46 // Now that the time left before write-back is known, notify
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);
55 void 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);
65 std::pair<ReadState *, int> NewPair(User, ReadAdvance);
66 Users.insert(NewPair);
69 void 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)
77 void ReadState::cycleEvent() {
78 // Update the total number of cycles.
79 if (DependentWrites && TotalCycles) {
84 // Bail out immediately if we don't know how many cycles are left.
85 if (CyclesLeft == UNKNOWN_CYCLES)
90 IsReady = !CyclesLeft;
95 void WriteState::dump() const {
96 dbgs() << "{ OpIdx=" << WD.OpIndex << ", Lat=" << getLatency() << ", RegID "
97 << getRegisterID() << ", Cycles Left=" << getCyclesLeft() << " }";
100 void WriteRef::dump() const {
101 dbgs() << "IID=" << getSourceIndex() << ' ';
103 getWriteState()->dump();
109 void Instruction::dispatch(unsigned RCUToken) {
110 assert(Stage == IS_INVALID);
111 Stage = IS_AVAILABLE;
112 RCUTokenID = RCUToken;
114 // Check if input operands are already available.
118 void Instruction::execute() {
119 assert(Stage == IS_READY);
120 Stage = IS_EXECUTING;
122 // Set the cycles left before the write-back stage.
123 CyclesLeft = Desc.MaxLatency;
125 for (UniqueDef &Def : Defs)
126 Def->onInstructionIssued();
128 // Transition to the "executed" stage if this is a zero-latency instruction.
133 void Instruction::update() {
134 assert(isDispatched() && "Unexpected instruction stage found!");
136 if (!llvm::all_of(Uses, [](const UniqueUse &Use) { return Use->isReady(); }))
139 // A partial register write cannot complete before a dependent write.
140 auto IsDefReady = [&](const UniqueDef &Def) {
141 if (const WriteState *Write = Def->getDependentWrite()) {
142 int WriteLatency = Write->getCyclesLeft();
143 if (WriteLatency == UNKNOWN_CYCLES)
145 return static_cast<unsigned>(WriteLatency) < Desc.MaxLatency;
150 if (llvm::all_of(Defs, IsDefReady))
154 void Instruction::cycleEvent() {
158 if (isDispatched()) {
159 for (UniqueUse &Use : Uses)
166 assert(isExecuting() && "Instruction not in-flight?");
167 assert(CyclesLeft && "Instruction already executed?");
168 for (UniqueDef &Def : Defs)
175 const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();