Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp
35290 views
1
//===--------------------- ResourcePressureView.cpp -------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
/// \file
9
///
10
/// This file implements methods in the ResourcePressureView interface.
11
///
12
//===----------------------------------------------------------------------===//
13
14
#include "Views/ResourcePressureView.h"
15
#include "llvm/Support/FormattedStream.h"
16
#include "llvm/Support/raw_ostream.h"
17
18
namespace llvm {
19
namespace mca {
20
21
ResourcePressureView::ResourcePressureView(const llvm::MCSubtargetInfo &sti,
22
MCInstPrinter &Printer,
23
ArrayRef<MCInst> S)
24
: InstructionView(sti, Printer, S), LastInstructionIdx(0) {
25
// Populate the map of resource descriptors.
26
unsigned R2VIndex = 0;
27
const MCSchedModel &SM = getSubTargetInfo().getSchedModel();
28
for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
29
const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
30
unsigned NumUnits = ProcResource.NumUnits;
31
// Skip groups and invalid resources with zero units.
32
if (ProcResource.SubUnitsIdxBegin || !NumUnits)
33
continue;
34
35
Resource2VecIndex.insert(std::pair<unsigned, unsigned>(I, R2VIndex));
36
R2VIndex += ProcResource.NumUnits;
37
}
38
39
NumResourceUnits = R2VIndex;
40
ResourceUsage.resize(NumResourceUnits * (getSource().size() + 1));
41
std::fill(ResourceUsage.begin(), ResourceUsage.end(), 0.0);
42
}
43
44
void ResourcePressureView::onEvent(const HWInstructionEvent &Event) {
45
if (Event.Type == HWInstructionEvent::Dispatched) {
46
LastInstructionIdx = Event.IR.getSourceIndex();
47
return;
48
}
49
50
// We're only interested in Issue events.
51
if (Event.Type != HWInstructionEvent::Issued)
52
return;
53
54
const auto &IssueEvent = static_cast<const HWInstructionIssuedEvent &>(Event);
55
ArrayRef<llvm::MCInst> Source = getSource();
56
const unsigned SourceIdx = Event.IR.getSourceIndex() % Source.size();
57
for (const std::pair<ResourceRef, ReleaseAtCycles> &Use :
58
IssueEvent.UsedResources) {
59
const ResourceRef &RR = Use.first;
60
assert(Resource2VecIndex.contains(RR.first));
61
unsigned R2VIndex = Resource2VecIndex[RR.first];
62
R2VIndex += llvm::countr_zero(RR.second);
63
ResourceUsage[R2VIndex + NumResourceUnits * SourceIdx] += Use.second;
64
ResourceUsage[R2VIndex + NumResourceUnits * Source.size()] += Use.second;
65
}
66
}
67
68
static void printColumnNames(formatted_raw_ostream &OS,
69
const MCSchedModel &SM) {
70
unsigned Column = OS.getColumn();
71
for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
72
I < E; ++I) {
73
const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
74
unsigned NumUnits = ProcResource.NumUnits;
75
// Skip groups and invalid resources with zero units.
76
if (ProcResource.SubUnitsIdxBegin || !NumUnits)
77
continue;
78
79
for (unsigned J = 0; J < NumUnits; ++J) {
80
Column += 7;
81
OS << "[" << ResourceIndex;
82
if (NumUnits > 1)
83
OS << '.' << J;
84
OS << ']';
85
OS.PadToColumn(Column);
86
}
87
88
ResourceIndex++;
89
}
90
}
91
92
static void printResourcePressure(formatted_raw_ostream &OS, double Pressure,
93
unsigned Col) {
94
if (!Pressure || Pressure < 0.005) {
95
OS << " - ";
96
} else {
97
// Round to the value to the nearest hundredth and then print it.
98
OS << format("%.2f", floor((Pressure * 100) + 0.5) / 100);
99
}
100
OS.PadToColumn(Col);
101
}
102
103
void ResourcePressureView::printResourcePressurePerIter(raw_ostream &OS) const {
104
std::string Buffer;
105
raw_string_ostream TempStream(Buffer);
106
formatted_raw_ostream FOS(TempStream);
107
108
FOS << "\n\nResources:\n";
109
const MCSchedModel &SM = getSubTargetInfo().getSchedModel();
110
for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
111
I < E; ++I) {
112
const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
113
unsigned NumUnits = ProcResource.NumUnits;
114
// Skip groups and invalid resources with zero units.
115
if (ProcResource.SubUnitsIdxBegin || !NumUnits)
116
continue;
117
118
for (unsigned J = 0; J < NumUnits; ++J) {
119
FOS << '[' << ResourceIndex;
120
if (NumUnits > 1)
121
FOS << '.' << J;
122
FOS << ']';
123
FOS.PadToColumn(6);
124
FOS << "- " << ProcResource.Name << '\n';
125
}
126
127
ResourceIndex++;
128
}
129
130
FOS << "\n\nResource pressure per iteration:\n";
131
FOS.flush();
132
printColumnNames(FOS, SM);
133
FOS << '\n';
134
FOS.flush();
135
136
ArrayRef<llvm::MCInst> Source = getSource();
137
const unsigned Executions = LastInstructionIdx / Source.size() + 1;
138
for (unsigned I = 0, E = NumResourceUnits; I < E; ++I) {
139
double Usage = ResourceUsage[I + Source.size() * E];
140
printResourcePressure(FOS, Usage / Executions, (I + 1) * 7);
141
}
142
143
FOS.flush();
144
OS << Buffer;
145
}
146
147
void ResourcePressureView::printResourcePressurePerInst(raw_ostream &OS) const {
148
std::string Buffer;
149
raw_string_ostream TempStream(Buffer);
150
formatted_raw_ostream FOS(TempStream);
151
152
FOS << "\n\nResource pressure by instruction:\n";
153
printColumnNames(FOS, getSubTargetInfo().getSchedModel());
154
FOS << "Instructions:\n";
155
156
unsigned InstrIndex = 0;
157
ArrayRef<llvm::MCInst> Source = getSource();
158
const unsigned Executions = LastInstructionIdx / Source.size() + 1;
159
for (const MCInst &MCI : Source) {
160
unsigned BaseEltIdx = InstrIndex * NumResourceUnits;
161
for (unsigned J = 0; J < NumResourceUnits; ++J) {
162
double Usage = ResourceUsage[J + BaseEltIdx];
163
printResourcePressure(FOS, Usage / Executions, (J + 1) * 7);
164
}
165
166
FOS << printInstructionString(MCI) << '\n';
167
FOS.flush();
168
OS << Buffer;
169
Buffer = "";
170
171
++InstrIndex;
172
}
173
}
174
175
json::Value ResourcePressureView::toJSON() const {
176
// We're dumping the instructions and the ResourceUsage array.
177
json::Array ResourcePressureInfo;
178
179
// The ResourceUsage matrix is sparse, so we only consider
180
// non-zero values.
181
ArrayRef<llvm::MCInst> Source = getSource();
182
const unsigned Executions = LastInstructionIdx / Source.size() + 1;
183
for (const auto &R : enumerate(ResourceUsage)) {
184
const ReleaseAtCycles &RU = R.value();
185
if (RU.getNumerator() == 0)
186
continue;
187
unsigned InstructionIndex = R.index() / NumResourceUnits;
188
unsigned ResourceIndex = R.index() % NumResourceUnits;
189
double Usage = RU / Executions;
190
ResourcePressureInfo.push_back(
191
json::Object({{"InstructionIndex", InstructionIndex},
192
{"ResourceIndex", ResourceIndex},
193
{"ResourceUsage", Usage}}));
194
}
195
196
json::Object JO({{"ResourcePressureInfo", std::move(ResourcePressureInfo)}});
197
return JO;
198
}
199
} // namespace mca
200
} // namespace llvm
201
202