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 "ResourcePressureView.h"
16 #include "llvm/Support/FormattedStream.h"
17 #include "llvm/Support/raw_ostream.h"
18
19 namespace mca {
20
21 using namespace llvm;
22
initialize()23 void ResourcePressureView::initialize() {
24 // Populate the map of resource descriptors.
25 unsigned R2VIndex = 0;
26 const MCSchedModel &SM = STI.getSchedModel();
27 for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
28 const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
29 unsigned NumUnits = ProcResource.NumUnits;
30 // Skip groups and invalid resources with zero units.
31 if (ProcResource.SubUnitsIdxBegin || !NumUnits)
32 continue;
33
34 Resource2VecIndex.insert(std::pair<unsigned, unsigned>(I, R2VIndex));
35 R2VIndex += ProcResource.NumUnits;
36 }
37
38 NumResourceUnits = R2VIndex;
39 ResourceUsage.resize(NumResourceUnits * (Source.size() + 1));
40 std::fill(ResourceUsage.begin(), ResourceUsage.end(), 0.0);
41 }
42
onEvent(const HWInstructionEvent & Event)43 void ResourcePressureView::onEvent(const HWInstructionEvent &Event) {
44 // We're only interested in Issue events.
45 if (Event.Type != HWInstructionEvent::Issued)
46 return;
47 const auto &IssueEvent = static_cast<const HWInstructionIssuedEvent &>(Event);
48 const unsigned SourceIdx = Event.IR.getSourceIndex() % Source.size();
49 for (const std::pair<ResourceRef, double> &Use : IssueEvent.UsedResources) {
50 const ResourceRef &RR = Use.first;
51 assert(Resource2VecIndex.find(RR.first) != Resource2VecIndex.end());
52 unsigned R2VIndex = Resource2VecIndex[RR.first];
53 R2VIndex += countTrailingZeros(RR.second);
54 ResourceUsage[R2VIndex + NumResourceUnits * SourceIdx] += Use.second;
55 ResourceUsage[R2VIndex + NumResourceUnits * Source.size()] += Use.second;
56 }
57 }
58
printColumnNames(formatted_raw_ostream & OS,const MCSchedModel & SM)59 static void printColumnNames(formatted_raw_ostream &OS,
60 const MCSchedModel &SM) {
61 unsigned Column = OS.getColumn();
62 for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
63 I < E; ++I) {
64 const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
65 unsigned NumUnits = ProcResource.NumUnits;
66 // Skip groups and invalid resources with zero units.
67 if (ProcResource.SubUnitsIdxBegin || !NumUnits)
68 continue;
69
70 for (unsigned J = 0; J < NumUnits; ++J) {
71 Column += 7;
72 OS << "[" << ResourceIndex;
73 if (NumUnits > 1)
74 OS << '.' << J;
75 OS << ']';
76 OS.PadToColumn(Column);
77 }
78
79 ResourceIndex++;
80 }
81 }
82
printResourcePressure(formatted_raw_ostream & OS,double Pressure,unsigned Col)83 static void printResourcePressure(formatted_raw_ostream &OS, double Pressure,
84 unsigned Col) {
85 if (!Pressure || Pressure < 0.005) {
86 OS << " - ";
87 } else {
88 // Round to the value to the nearest hundredth and then print it.
89 OS << format("%.2f", floor((Pressure * 100) + 0.5) / 100);
90 }
91 OS.PadToColumn(Col);
92 }
93
printResourcePressurePerIteration(raw_ostream & OS,unsigned Executions) const94 void ResourcePressureView::printResourcePressurePerIteration(
95 raw_ostream &OS, unsigned Executions) const {
96 std::string Buffer;
97 raw_string_ostream TempStream(Buffer);
98 formatted_raw_ostream FOS(TempStream);
99
100 FOS << "\n\nResources:\n";
101 const MCSchedModel &SM = STI.getSchedModel();
102 for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
103 I < E; ++I) {
104 const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
105 unsigned NumUnits = ProcResource.NumUnits;
106 // Skip groups and invalid resources with zero units.
107 if (ProcResource.SubUnitsIdxBegin || !NumUnits)
108 continue;
109
110 for (unsigned J = 0; J < NumUnits; ++J) {
111 FOS << '[' << ResourceIndex;
112 if (NumUnits > 1)
113 FOS << '.' << J;
114 FOS << ']';
115 FOS.PadToColumn(6);
116 FOS << "- " << ProcResource.Name << '\n';
117 }
118
119 ResourceIndex++;
120 }
121
122 FOS << "\n\nResource pressure per iteration:\n";
123 FOS.flush();
124 printColumnNames(FOS, SM);
125 FOS << '\n';
126 FOS.flush();
127
128 for (unsigned I = 0, E = NumResourceUnits; I < E; ++I) {
129 double Usage = ResourceUsage[I + Source.size() * E];
130 printResourcePressure(FOS, Usage / Executions, (I + 1) * 7);
131 }
132
133 FOS.flush();
134 OS << Buffer;
135 }
136
printResourcePressurePerInstruction(raw_ostream & OS,unsigned Executions) const137 void ResourcePressureView::printResourcePressurePerInstruction(
138 raw_ostream &OS, unsigned Executions) const {
139 std::string Buffer;
140 raw_string_ostream TempStream(Buffer);
141 formatted_raw_ostream FOS(TempStream);
142
143 FOS << "\n\nResource pressure by instruction:\n";
144 printColumnNames(FOS, STI.getSchedModel());
145 FOS << "Instructions:\n";
146
147 std::string Instruction;
148 raw_string_ostream InstrStream(Instruction);
149
150 for (unsigned I = 0, E = Source.size(); I < E; ++I) {
151 for (unsigned J = 0; J < NumResourceUnits; ++J) {
152 double Usage = ResourceUsage[J + I * NumResourceUnits];
153 printResourcePressure(FOS, Usage / Executions, (J + 1) * 7);
154 }
155
156 MCIP.printInst(&Source.getMCInstFromIndex(I), InstrStream, "", STI);
157 InstrStream.flush();
158 StringRef Str(Instruction);
159
160 // Remove any tabs or spaces at the beginning of the instruction.
161 Str = Str.ltrim();
162
163 FOS << Str << '\n';
164 Instruction = "";
165
166 FOS.flush();
167 OS << Buffer;
168 Buffer = "";
169 }
170 }
171 } // namespace mca
172