1 //===--------------------- ResourcePressureView.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 /// \file
10 ///
11 /// This file implements methods in the ResourcePressureView interface.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #include "Views/ResourcePressureView.h"
16 #include "llvm/Support/FormattedStream.h"
17 #include "llvm/Support/raw_ostream.h"
18
19 namespace llvm {
20 namespace mca {
21
ResourcePressureView(const llvm::MCSubtargetInfo & sti,MCInstPrinter & Printer,ArrayRef<MCInst> S)22 ResourcePressureView::ResourcePressureView(const llvm::MCSubtargetInfo &sti,
23 MCInstPrinter &Printer,
24 ArrayRef<MCInst> S)
25 : STI(sti), MCIP(Printer), Source(S), LastInstructionIdx(0) {
26 // Populate the map of resource descriptors.
27 unsigned R2VIndex = 0;
28 const MCSchedModel &SM = STI.getSchedModel();
29 for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
30 const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
31 unsigned NumUnits = ProcResource.NumUnits;
32 // Skip groups and invalid resources with zero units.
33 if (ProcResource.SubUnitsIdxBegin || !NumUnits)
34 continue;
35
36 Resource2VecIndex.insert(std::pair<unsigned, unsigned>(I, R2VIndex));
37 R2VIndex += ProcResource.NumUnits;
38 }
39
40 NumResourceUnits = R2VIndex;
41 ResourceUsage.resize(NumResourceUnits * (Source.size() + 1));
42 std::fill(ResourceUsage.begin(), ResourceUsage.end(), 0.0);
43 }
44
onEvent(const HWInstructionEvent & Event)45 void ResourcePressureView::onEvent(const HWInstructionEvent &Event) {
46 if (Event.Type == HWInstructionEvent::Dispatched) {
47 LastInstructionIdx = Event.IR.getSourceIndex();
48 return;
49 }
50
51 // We're only interested in Issue events.
52 if (Event.Type != HWInstructionEvent::Issued)
53 return;
54
55 const auto &IssueEvent = static_cast<const HWInstructionIssuedEvent &>(Event);
56 const unsigned SourceIdx = Event.IR.getSourceIndex() % Source.size();
57 for (const std::pair<ResourceRef, ResourceCycles> &Use :
58 IssueEvent.UsedResources) {
59 const ResourceRef &RR = Use.first;
60 assert(Resource2VecIndex.find(RR.first) != Resource2VecIndex.end());
61 unsigned R2VIndex = Resource2VecIndex[RR.first];
62 R2VIndex += countTrailingZeros(RR.second);
63 ResourceUsage[R2VIndex + NumResourceUnits * SourceIdx] += Use.second;
64 ResourceUsage[R2VIndex + NumResourceUnits * Source.size()] += Use.second;
65 }
66 }
67
printColumnNames(formatted_raw_ostream & OS,const MCSchedModel & SM)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
printResourcePressure(formatted_raw_ostream & OS,double Pressure,unsigned Col)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
printResourcePressurePerIter(raw_ostream & OS) const103 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 = STI.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 const unsigned Executions = LastInstructionIdx / Source.size() + 1;
137 for (unsigned I = 0, E = NumResourceUnits; I < E; ++I) {
138 double Usage = ResourceUsage[I + Source.size() * E];
139 printResourcePressure(FOS, Usage / Executions, (I + 1) * 7);
140 }
141
142 FOS.flush();
143 OS << Buffer;
144 }
145
printResourcePressurePerInst(raw_ostream & OS) const146 void ResourcePressureView::printResourcePressurePerInst(raw_ostream &OS) const {
147 std::string Buffer;
148 raw_string_ostream TempStream(Buffer);
149 formatted_raw_ostream FOS(TempStream);
150
151 FOS << "\n\nResource pressure by instruction:\n";
152 printColumnNames(FOS, STI.getSchedModel());
153 FOS << "Instructions:\n";
154
155 std::string Instruction;
156 raw_string_ostream InstrStream(Instruction);
157
158 unsigned InstrIndex = 0;
159 const unsigned Executions = LastInstructionIdx / Source.size() + 1;
160 for (const MCInst &MCI : Source) {
161 unsigned BaseEltIdx = InstrIndex * NumResourceUnits;
162 for (unsigned J = 0; J < NumResourceUnits; ++J) {
163 double Usage = ResourceUsage[J + BaseEltIdx];
164 printResourcePressure(FOS, Usage / Executions, (J + 1) * 7);
165 }
166
167 MCIP.printInst(&MCI, InstrStream, "", STI);
168 InstrStream.flush();
169 StringRef Str(Instruction);
170
171 // Remove any tabs or spaces at the beginning of the instruction.
172 Str = Str.ltrim();
173
174 FOS << Str << '\n';
175 Instruction = "";
176
177 FOS.flush();
178 OS << Buffer;
179 Buffer = "";
180
181 ++InstrIndex;
182 }
183 }
184 } // namespace mca
185 } // namespace llvm
186