1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
//===--------------------- Backend.cpp --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// Implementation of class Backend which emulates an hardware OoO backend.
///
//===----------------------------------------------------------------------===//
#include "Backend.h"
#include "HWEventListener.h"
#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/Support/Debug.h"
namespace mca {
#define DEBUG_TYPE "llvm-mca"
using namespace llvm;
void Backend::addEventListener(HWEventListener *Listener) {
if (Listener)
Listeners.insert(Listener);
}
void Backend::runCycle(unsigned Cycle) {
notifyCycleBegin(Cycle);
if (!SM->hasNext()) {
notifyCycleEnd(Cycle);
return;
}
InstRef IR = SM->peekNext();
const InstrDesc *Desc = &IB->getOrCreateInstrDesc(STI, *IR.second);
while (DU->isAvailable(Desc->NumMicroOps) && DU->canDispatch(*Desc)) {
Instruction *NewIS = IB->createInstruction(STI, *DU, IR.first, *IR.second);
Instructions[IR.first] = std::unique_ptr<Instruction>(NewIS);
NewIS->setRCUTokenID(DU->dispatch(IR.first, NewIS));
// If this is a zero latency instruction, then we don't need to dispatch
// it. Instead, we can mark it as executed.
if (NewIS->isZeroLatency())
notifyInstructionExecuted(IR.first);
// Check if we have dispatched all the instructions.
SM->updateNext();
if (!SM->hasNext())
break;
// Prepare for the next round.
IR = SM->peekNext();
Desc = &IB->getOrCreateInstrDesc(STI, *IR.second);
}
notifyCycleEnd(Cycle);
}
void Backend::notifyCycleBegin(unsigned Cycle) {
DEBUG(dbgs() << "[E] Cycle begin: " << Cycle << '\n');
for (HWEventListener *Listener : Listeners)
Listener->onCycleBegin(Cycle);
DU->cycleEvent(Cycle);
HWS->cycleEvent(Cycle);
}
void Backend::notifyInstructionDispatched(unsigned Index) {
DEBUG(dbgs() << "[E] Instruction Dispatched: " << Index << '\n');
for (HWEventListener *Listener : Listeners)
Listener->onInstructionDispatched(Index);
}
void Backend::notifyInstructionReady(unsigned Index) {
DEBUG(dbgs() << "[E] Instruction Ready: " << Index << '\n');
for (HWEventListener *Listener : Listeners)
Listener->onInstructionReady(Index);
}
void Backend::notifyInstructionIssued(
unsigned Index, const ArrayRef<std::pair<ResourceRef, unsigned>> &Used) {
DEBUG(
dbgs() << "[E] Instruction Issued: " << Index << '\n';
for (const std::pair<ResourceRef, unsigned> &Resource : Used) {
dbgs() << "[E] Resource Used: [" << Resource.first.first << '.'
<< Resource.first.second << "]\n";
dbgs() << " cycles: " << Resource.second << '\n';
}
);
for (HWEventListener *Listener : Listeners)
Listener->onInstructionIssued(Index, Used);
}
void Backend::notifyInstructionExecuted(unsigned Index) {
DEBUG(dbgs() << "[E] Instruction Executed: " << Index << '\n');
for (HWEventListener *Listener : Listeners)
Listener->onInstructionExecuted(Index);
const Instruction &IS = *Instructions[Index];
DU->onInstructionExecuted(IS.getRCUTokenID());
}
void Backend::notifyInstructionRetired(unsigned Index) {
DEBUG(dbgs() << "[E] Instruction Retired: " << Index << '\n');
for (HWEventListener *Listener : Listeners)
Listener->onInstructionRetired(Index);
const Instruction &IS = *Instructions[Index];
DU->invalidateRegisterMappings(IS);
Instructions.erase(Index);
}
void Backend::notifyResourceAvailable(const ResourceRef &RR) {
DEBUG(dbgs() << "[E] Resource Available: [" << RR.first << '.' << RR.second
<< "]\n");
for (HWEventListener *Listener : Listeners)
Listener->onResourceAvailable(RR);
}
void Backend::notifyCycleEnd(unsigned Cycle) {
DEBUG(dbgs() << "[E] Cycle end: " << Cycle << "\n\n");
for (HWEventListener *Listener : Listeners)
Listener->onCycleEnd(Cycle);
}
} // namespace mca.
|