1 //===--------------------- ResourcePressureView.cpp -------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file implements methods in the ResourcePressureView interface.
12 //===----------------------------------------------------------------------===//
14 #include "Views/ResourcePressureView.h"
15 #include "llvm/Support/FormattedStream.h"
16 #include "llvm/Support/raw_ostream.h"
21 ResourcePressureView::ResourcePressureView(const llvm::MCSubtargetInfo
&sti
,
22 MCInstPrinter
&Printer
,
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
)
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();
50 // We're only interested in Issue events.
51 if (Event
.Type
!= HWInstructionEvent::Issued
)
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();
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
)
78 for (unsigned J
= 0; J
< NumUnits
; ++J
) {
80 OS
<< "[" << ResourceIndex
;
84 OS
.PadToColumn(Column
);
91 static void printResourcePressure(formatted_raw_ostream
&OS
, double Pressure
,
93 if (!Pressure
|| Pressure
< 0.005) {
96 // Round to the value to the nearest hundredth and then print it.
97 OS
<< format("%.2f", floor((Pressure
* 100) + 0.5) / 100);
102 void ResourcePressureView::printResourcePressurePerIter(raw_ostream
&OS
) const {
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();
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
)
117 for (unsigned J
= 0; J
< NumUnits
; ++J
) {
118 FOS
<< '[' << ResourceIndex
;
123 FOS
<< "- " << ProcResource
.Name
<< '\n';
129 FOS
<< "\n\nResource pressure per iteration:\n";
131 printColumnNames(FOS
, SM
);
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);
145 void ResourcePressureView::printResourcePressurePerInst(raw_ostream
&OS
) const {
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
);
168 StringRef
Str(Instruction
);
170 // Remove any tabs or spaces at the beginning of the instruction.