]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-mca/ResourcePressureView.cpp
MFC r345703:
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / llvm-mca / ResourcePressureView.cpp
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
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, 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
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
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
94 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
137 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