blob: 1b9620f628c208cdd7c531934ef6cc6555daf26a [file] [log] [blame]
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +00001//===--------------------- 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/raw_ostream.h"
17
18namespace mca {
19
20using namespace llvm;
21
Andrea Di Biagio0c541292018-03-10 16:55:07 +000022void ResourcePressureView::initialize() {
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000023 // Populate the map of resource descriptors.
24 unsigned R2VIndex = 0;
25 const MCSchedModel &SM = STI.getSchedModel();
26 for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
27 const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
28 unsigned NumUnits = ProcResource.NumUnits;
29 // Skip groups and invalid resources with zero units.
30 if (ProcResource.SubUnitsIdxBegin || !NumUnits)
31 continue;
32
Andrea Di Biagio0c541292018-03-10 16:55:07 +000033 Resource2VecIndex.insert(std::pair<uint64_t, unsigned>(I, R2VIndex));
Andrea Di Biagio3a6b0922018-03-08 13:05:02 +000034 R2VIndex += ProcResource.NumUnits;
35 }
36
37 NumResourceUnits = R2VIndex;
38 ResourceUsage.resize(NumResourceUnits * (Source.size() + 1));
39 std::fill(ResourceUsage.begin(), ResourceUsage.end(), 0);
40}
41
42void ResourcePressureView::onInstructionIssued(
43 unsigned Index, const ArrayRef<std::pair<ResourceRef, unsigned>> &Used) {
44 unsigned SourceIdx = Index % Source.size();
45 for (const std::pair<ResourceRef, unsigned> &Use : Used) {
46 const ResourceRef &RR = Use.first;
47 assert(Resource2VecIndex.find(RR.first) != Resource2VecIndex.end());
48 unsigned R2VIndex = Resource2VecIndex[RR.first];
49 R2VIndex += countTrailingZeros(RR.second);
50 ResourceUsage[R2VIndex + NumResourceUnits * SourceIdx] += Use.second;
51 ResourceUsage[R2VIndex + NumResourceUnits * Source.size()] += Use.second;
52 }
53}
54
55static void printColumnNames(raw_string_ostream &OS, const MCSchedModel &SM) {
56 for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
57 I < E; ++I) {
58 const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
59 unsigned NumUnits = ProcResource.NumUnits;
60 // Skip groups and invalid resources with zero units.
61 if (ProcResource.SubUnitsIdxBegin || !NumUnits)
62 continue;
63
64 if (NumUnits == 1) {
65 OS << '[' << ResourceIndex << ']';
66 if (ResourceIndex < 10)
67 OS << " ";
68 else
69 OS << " ";
70 ResourceIndex++;
71 continue;
72 }
73
74 for (unsigned J = 0; J < NumUnits; ++J) {
75 OS << "[" << ResourceIndex << '.' << J << ']';
76 if (ResourceIndex < 10)
77 OS << " ";
78 else
79 OS << ' ';
80 }
81 ResourceIndex++;
82 }
83}
84
85void ResourcePressureView::printResourcePressurePerIteration(
86 raw_ostream &OS, unsigned Executions) const {
87 std::string Buffer;
88 raw_string_ostream TempStream(Buffer);
89
90 TempStream << "\n\nResources:\n";
91 const MCSchedModel &SM = STI.getSchedModel();
92 for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
93 I < E; ++I) {
94 const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
95 unsigned NumUnits = ProcResource.NumUnits;
96 // Skip groups and invalid resources with zero units.
97 if (ProcResource.SubUnitsIdxBegin || !NumUnits)
98 continue;
99
100 for (unsigned J = 0; J < NumUnits; ++J) {
101 TempStream << '[' << ResourceIndex;
102 if (NumUnits > 1)
103 TempStream << '.' << J;
104 TempStream << "] - " << ProcResource.Name << '\n';
105 }
106
107 ResourceIndex++;
108 }
109
110 TempStream << "\n\nResource pressure per iteration:\n";
111 printColumnNames(TempStream, SM);
112 TempStream << '\n';
113
114 for (unsigned I = 0; I < NumResourceUnits; ++I) {
115 unsigned Usage = ResourceUsage[I + Source.size() * NumResourceUnits];
116 if (!Usage) {
117 TempStream << " - ";
118 continue;
119 }
120
121 double Pressure = (double)Usage / Executions;
122 TempStream << format("%.2f", Pressure);
123 if (Pressure < 10.0)
124 TempStream << " ";
125 else if (Pressure < 100.0)
126 TempStream << " ";
127 else
128 TempStream << ' ';
129 }
130
131 TempStream.flush();
132 OS << Buffer;
133}
134
135void ResourcePressureView::printResourcePressurePerInstruction(
136 raw_ostream &OS, unsigned Executions) const {
137 std::string Buffer;
138 raw_string_ostream TempStream(Buffer);
139
140 TempStream << "\n\nResource pressure by instruction:\n";
141 printColumnNames(TempStream, STI.getSchedModel());
142 TempStream << "\tInstructions:\n";
143
144 for (unsigned I = 0, E = Source.size(); I < E; ++I) {
145 for (unsigned J = 0; J < NumResourceUnits; ++J) {
146 unsigned Usage = ResourceUsage[J + I * NumResourceUnits];
147 if (Usage == 0) {
148 TempStream << " - ";
149 } else {
150 double Pressure = (double)Usage / Executions;
151 if (Pressure < 0.005) {
152 TempStream << " - ";
153 } else {
154 TempStream << format("%.2f", Pressure);
155 if (Pressure < 10.0)
156 TempStream << " ";
157 else if (Pressure < 100.0)
158 TempStream << " ";
159 else
160 TempStream << ' ';
161 }
162 }
163 }
164
165 MCIP.printInst(&Source.getMCInstFromIndex(I), TempStream, "", STI);
166 TempStream << '\n';
167 TempStream.flush();
168 OS << Buffer;
169 Buffer = "";
170 }
171}
172
173} // namespace mca