[InstCombine] Signed saturation patterns
[llvm-complete.git] / tools / llvm-mca / Views / ResourcePressureView.cpp
blob38a2478cf4fecebd9caf104ac71d411c0716ef30
1 //===--------------------- ResourcePressureView.cpp -------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 ///
10 /// This file implements methods in the ResourcePressureView interface.
11 ///
12 //===----------------------------------------------------------------------===//
14 #include "Views/ResourcePressureView.h"
15 #include "llvm/Support/FormattedStream.h"
16 #include "llvm/Support/raw_ostream.h"
18 namespace llvm {
19 namespace mca {
21 ResourcePressureView::ResourcePressureView(const llvm::MCSubtargetInfo &sti,
22 MCInstPrinter &Printer,
23 ArrayRef<MCInst> S)
24 : STI(sti), MCIP(Printer), Source(S), LastInstructionIdx(0) {
25 // Populate the map of resource descriptors.
26 unsigned R2VIndex = 0;
27 const MCSchedModel &SM = STI.getSchedModel();
28 for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
29 const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
30 unsigned NumUnits = ProcResource.NumUnits;
31 // Skip groups and invalid resources with zero units.
32 if (ProcResource.SubUnitsIdxBegin || !NumUnits)
33 continue;
35 Resource2VecIndex.insert(std::pair<unsigned, unsigned>(I, R2VIndex));
36 R2VIndex += ProcResource.NumUnits;
39 NumResourceUnits = R2VIndex;
40 ResourceUsage.resize(NumResourceUnits * (Source.size() + 1));
41 std::fill(ResourceUsage.begin(), ResourceUsage.end(), 0.0);
44 void ResourcePressureView::onEvent(const HWInstructionEvent &Event) {
45 if (Event.Type == HWInstructionEvent::Dispatched) {
46 LastInstructionIdx = Event.IR.getSourceIndex();
47 return;
50 // We're only interested in Issue events.
51 if (Event.Type != HWInstructionEvent::Issued)
52 return;
54 const auto &IssueEvent = static_cast<const HWInstructionIssuedEvent &>(Event);
55 const unsigned SourceIdx = Event.IR.getSourceIndex() % Source.size();
56 for (const std::pair<ResourceRef, ResourceCycles> &Use :
57 IssueEvent.UsedResources) {
58 const ResourceRef &RR = Use.first;
59 assert(Resource2VecIndex.find(RR.first) != Resource2VecIndex.end());
60 unsigned R2VIndex = Resource2VecIndex[RR.first];
61 R2VIndex += countTrailingZeros(RR.second);
62 ResourceUsage[R2VIndex + NumResourceUnits * SourceIdx] += Use.second;
63 ResourceUsage[R2VIndex + NumResourceUnits * Source.size()] += Use.second;
67 static void printColumnNames(formatted_raw_ostream &OS,
68 const MCSchedModel &SM) {
69 unsigned Column = OS.getColumn();
70 for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
71 I < E; ++I) {
72 const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
73 unsigned NumUnits = ProcResource.NumUnits;
74 // Skip groups and invalid resources with zero units.
75 if (ProcResource.SubUnitsIdxBegin || !NumUnits)
76 continue;
78 for (unsigned J = 0; J < NumUnits; ++J) {
79 Column += 7;
80 OS << "[" << ResourceIndex;
81 if (NumUnits > 1)
82 OS << '.' << J;
83 OS << ']';
84 OS.PadToColumn(Column);
87 ResourceIndex++;
91 static void printResourcePressure(formatted_raw_ostream &OS, double Pressure,
92 unsigned Col) {
93 if (!Pressure || Pressure < 0.005) {
94 OS << " - ";
95 } else {
96 // Round to the value to the nearest hundredth and then print it.
97 OS << format("%.2f", floor((Pressure * 100) + 0.5) / 100);
99 OS.PadToColumn(Col);
102 void ResourcePressureView::printResourcePressurePerIter(raw_ostream &OS) const {
103 std::string Buffer;
104 raw_string_ostream TempStream(Buffer);
105 formatted_raw_ostream FOS(TempStream);
107 FOS << "\n\nResources:\n";
108 const MCSchedModel &SM = STI.getSchedModel();
109 for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
110 I < E; ++I) {
111 const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
112 unsigned NumUnits = ProcResource.NumUnits;
113 // Skip groups and invalid resources with zero units.
114 if (ProcResource.SubUnitsIdxBegin || !NumUnits)
115 continue;
117 for (unsigned J = 0; J < NumUnits; ++J) {
118 FOS << '[' << ResourceIndex;
119 if (NumUnits > 1)
120 FOS << '.' << J;
121 FOS << ']';
122 FOS.PadToColumn(6);
123 FOS << "- " << ProcResource.Name << '\n';
126 ResourceIndex++;
129 FOS << "\n\nResource pressure per iteration:\n";
130 FOS.flush();
131 printColumnNames(FOS, SM);
132 FOS << '\n';
133 FOS.flush();
135 const unsigned Executions = LastInstructionIdx / Source.size() + 1;
136 for (unsigned I = 0, E = NumResourceUnits; I < E; ++I) {
137 double Usage = ResourceUsage[I + Source.size() * E];
138 printResourcePressure(FOS, Usage / Executions, (I + 1) * 7);
141 FOS.flush();
142 OS << Buffer;
145 void ResourcePressureView::printResourcePressurePerInst(raw_ostream &OS) const {
146 std::string Buffer;
147 raw_string_ostream TempStream(Buffer);
148 formatted_raw_ostream FOS(TempStream);
150 FOS << "\n\nResource pressure by instruction:\n";
151 printColumnNames(FOS, STI.getSchedModel());
152 FOS << "Instructions:\n";
154 std::string Instruction;
155 raw_string_ostream InstrStream(Instruction);
157 unsigned InstrIndex = 0;
158 const unsigned Executions = LastInstructionIdx / Source.size() + 1;
159 for (const MCInst &MCI : Source) {
160 unsigned BaseEltIdx = InstrIndex * NumResourceUnits;
161 for (unsigned J = 0; J < NumResourceUnits; ++J) {
162 double Usage = ResourceUsage[J + BaseEltIdx];
163 printResourcePressure(FOS, Usage / Executions, (J + 1) * 7);
166 MCIP.printInst(&MCI, InstrStream, "", STI);
167 InstrStream.flush();
168 StringRef Str(Instruction);
170 // Remove any tabs or spaces at the beginning of the instruction.
171 Str = Str.ltrim();
173 FOS << Str << '\n';
174 Instruction = "";
176 FOS.flush();
177 OS << Buffer;
178 Buffer = "";
180 ++InstrIndex;
183 } // namespace mca
184 } // namespace llvm