xref: /llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp (revision db834837c2645ed2f3df1e77aff6a4aa14d6980c)
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 mca {
20 
21 using namespace llvm;
22 
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 
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, ResourceCycles> &Use :
50        IssueEvent.UsedResources) {
51     const ResourceRef &RR = Use.first;
52     assert(Resource2VecIndex.find(RR.first) != Resource2VecIndex.end());
53     unsigned R2VIndex = Resource2VecIndex[RR.first];
54     R2VIndex += countTrailingZeros(RR.second);
55     ResourceUsage[R2VIndex + NumResourceUnits * SourceIdx] += Use.second;
56     ResourceUsage[R2VIndex + NumResourceUnits * Source.size()] += Use.second;
57   }
58 }
59 
60 static void printColumnNames(formatted_raw_ostream &OS,
61                              const MCSchedModel &SM) {
62   unsigned Column = OS.getColumn();
63   for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
64        I < E; ++I) {
65     const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
66     unsigned NumUnits = ProcResource.NumUnits;
67     // Skip groups and invalid resources with zero units.
68     if (ProcResource.SubUnitsIdxBegin || !NumUnits)
69       continue;
70 
71     for (unsigned J = 0; J < NumUnits; ++J) {
72       Column += 7;
73       OS << "[" << ResourceIndex;
74       if (NumUnits > 1)
75         OS << '.' << J;
76       OS << ']';
77       OS.PadToColumn(Column);
78     }
79 
80     ResourceIndex++;
81   }
82 }
83 
84 static void printResourcePressure(formatted_raw_ostream &OS, double Pressure,
85                                   unsigned Col) {
86   if (!Pressure || Pressure < 0.005) {
87     OS << " - ";
88   } else {
89     // Round to the value to the nearest hundredth and then print it.
90     OS << format("%.2f", floor((Pressure * 100) + 0.5) / 100);
91   }
92   OS.PadToColumn(Col);
93 }
94 
95 void ResourcePressureView::printResourcePressurePerIteration(
96     raw_ostream &OS, unsigned Executions) const {
97   std::string Buffer;
98   raw_string_ostream TempStream(Buffer);
99   formatted_raw_ostream FOS(TempStream);
100 
101   FOS << "\n\nResources:\n";
102   const MCSchedModel &SM = STI.getSchedModel();
103   for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
104        I < E; ++I) {
105     const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
106     unsigned NumUnits = ProcResource.NumUnits;
107     // Skip groups and invalid resources with zero units.
108     if (ProcResource.SubUnitsIdxBegin || !NumUnits)
109       continue;
110 
111     for (unsigned J = 0; J < NumUnits; ++J) {
112       FOS << '[' << ResourceIndex;
113       if (NumUnits > 1)
114         FOS << '.' << J;
115       FOS << ']';
116       FOS.PadToColumn(6);
117       FOS << "- " << ProcResource.Name << '\n';
118     }
119 
120     ResourceIndex++;
121   }
122 
123   FOS << "\n\nResource pressure per iteration:\n";
124   FOS.flush();
125   printColumnNames(FOS, SM);
126   FOS << '\n';
127   FOS.flush();
128 
129   for (unsigned I = 0, E = NumResourceUnits; I < E; ++I) {
130     double Usage = ResourceUsage[I + Source.size() * E];
131     printResourcePressure(FOS, Usage / Executions, (I + 1) * 7);
132   }
133 
134   FOS.flush();
135   OS << Buffer;
136 }
137 
138 void ResourcePressureView::printResourcePressurePerInstruction(
139     raw_ostream &OS, unsigned Executions) const {
140   std::string Buffer;
141   raw_string_ostream TempStream(Buffer);
142   formatted_raw_ostream FOS(TempStream);
143 
144   FOS << "\n\nResource pressure by instruction:\n";
145   printColumnNames(FOS, STI.getSchedModel());
146   FOS << "Instructions:\n";
147 
148   std::string Instruction;
149   raw_string_ostream InstrStream(Instruction);
150 
151   for (unsigned I = 0, E = Source.size(); I < E; ++I) {
152     for (unsigned J = 0; J < NumResourceUnits; ++J) {
153       double Usage = ResourceUsage[J + I * NumResourceUnits];
154       printResourcePressure(FOS, Usage / Executions, (J + 1) * 7);
155     }
156 
157     MCIP.printInst(&Source.getMCInstFromIndex(I), InstrStream, "", STI);
158     InstrStream.flush();
159     StringRef Str(Instruction);
160 
161     // Remove any tabs or spaces at the beginning of the instruction.
162     Str = Str.ltrim();
163 
164     FOS << Str << '\n';
165     Instruction = "";
166 
167     FOS.flush();
168     OS << Buffer;
169     Buffer = "";
170   }
171 }
172 } // namespace mca
173