aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/tools/llvm-mca/Views/ResourcePressureView.cpp
diff options
context:
space:
mode:
authormonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
committermonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
commit06e5c21a835c0e923506c4ff27929f34e00761c2 (patch)
tree75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/libs/llvm12/tools/llvm-mca/Views/ResourcePressureView.cpp
parent03f024c4412e3aa613bb543cf1660176320ba8f4 (diff)
downloadydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz
fix ya.make
Diffstat (limited to 'contrib/libs/llvm12/tools/llvm-mca/Views/ResourcePressureView.cpp')
-rw-r--r--contrib/libs/llvm12/tools/llvm-mca/Views/ResourcePressureView.cpp200
1 files changed, 200 insertions, 0 deletions
diff --git a/contrib/libs/llvm12/tools/llvm-mca/Views/ResourcePressureView.cpp b/contrib/libs/llvm12/tools/llvm-mca/Views/ResourcePressureView.cpp
new file mode 100644
index 0000000000..77b3ba0b7c
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-mca/Views/ResourcePressureView.cpp
@@ -0,0 +1,200 @@
+//===--------------------- ResourcePressureView.cpp -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file implements methods in the ResourcePressureView interface.
+///
+//===----------------------------------------------------------------------===//
+
+#include "Views/ResourcePressureView.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+namespace mca {
+
+ResourcePressureView::ResourcePressureView(const llvm::MCSubtargetInfo &sti,
+ MCInstPrinter &Printer,
+ ArrayRef<MCInst> S)
+ : InstructionView(sti, Printer, S), LastInstructionIdx(0) {
+ // Populate the map of resource descriptors.
+ unsigned R2VIndex = 0;
+ const MCSchedModel &SM = getSubTargetInfo().getSchedModel();
+ for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
+ const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
+ unsigned NumUnits = ProcResource.NumUnits;
+ // Skip groups and invalid resources with zero units.
+ if (ProcResource.SubUnitsIdxBegin || !NumUnits)
+ continue;
+
+ Resource2VecIndex.insert(std::pair<unsigned, unsigned>(I, R2VIndex));
+ R2VIndex += ProcResource.NumUnits;
+ }
+
+ NumResourceUnits = R2VIndex;
+ ResourceUsage.resize(NumResourceUnits * (getSource().size() + 1));
+ std::fill(ResourceUsage.begin(), ResourceUsage.end(), 0.0);
+}
+
+void ResourcePressureView::onEvent(const HWInstructionEvent &Event) {
+ if (Event.Type == HWInstructionEvent::Dispatched) {
+ LastInstructionIdx = Event.IR.getSourceIndex();
+ return;
+ }
+
+ // We're only interested in Issue events.
+ if (Event.Type != HWInstructionEvent::Issued)
+ return;
+
+ const auto &IssueEvent = static_cast<const HWInstructionIssuedEvent &>(Event);
+ ArrayRef<llvm::MCInst> Source = getSource();
+ const unsigned SourceIdx = Event.IR.getSourceIndex() % Source.size();
+ for (const std::pair<ResourceRef, ResourceCycles> &Use :
+ IssueEvent.UsedResources) {
+ const ResourceRef &RR = Use.first;
+ assert(Resource2VecIndex.find(RR.first) != Resource2VecIndex.end());
+ unsigned R2VIndex = Resource2VecIndex[RR.first];
+ R2VIndex += countTrailingZeros(RR.second);
+ ResourceUsage[R2VIndex + NumResourceUnits * SourceIdx] += Use.second;
+ ResourceUsage[R2VIndex + NumResourceUnits * Source.size()] += Use.second;
+ }
+}
+
+static void printColumnNames(formatted_raw_ostream &OS,
+ const MCSchedModel &SM) {
+ unsigned Column = OS.getColumn();
+ for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
+ I < E; ++I) {
+ const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
+ unsigned NumUnits = ProcResource.NumUnits;
+ // Skip groups and invalid resources with zero units.
+ if (ProcResource.SubUnitsIdxBegin || !NumUnits)
+ continue;
+
+ for (unsigned J = 0; J < NumUnits; ++J) {
+ Column += 7;
+ OS << "[" << ResourceIndex;
+ if (NumUnits > 1)
+ OS << '.' << J;
+ OS << ']';
+ OS.PadToColumn(Column);
+ }
+
+ ResourceIndex++;
+ }
+}
+
+static void printResourcePressure(formatted_raw_ostream &OS, double Pressure,
+ unsigned Col) {
+ if (!Pressure || Pressure < 0.005) {
+ OS << " - ";
+ } else {
+ // Round to the value to the nearest hundredth and then print it.
+ OS << format("%.2f", floor((Pressure * 100) + 0.5) / 100);
+ }
+ OS.PadToColumn(Col);
+}
+
+void ResourcePressureView::printResourcePressurePerIter(raw_ostream &OS) const {
+ std::string Buffer;
+ raw_string_ostream TempStream(Buffer);
+ formatted_raw_ostream FOS(TempStream);
+
+ FOS << "\n\nResources:\n";
+ const MCSchedModel &SM = getSubTargetInfo().getSchedModel();
+ for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
+ I < E; ++I) {
+ const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
+ unsigned NumUnits = ProcResource.NumUnits;
+ // Skip groups and invalid resources with zero units.
+ if (ProcResource.SubUnitsIdxBegin || !NumUnits)
+ continue;
+
+ for (unsigned J = 0; J < NumUnits; ++J) {
+ FOS << '[' << ResourceIndex;
+ if (NumUnits > 1)
+ FOS << '.' << J;
+ FOS << ']';
+ FOS.PadToColumn(6);
+ FOS << "- " << ProcResource.Name << '\n';
+ }
+
+ ResourceIndex++;
+ }
+
+ FOS << "\n\nResource pressure per iteration:\n";
+ FOS.flush();
+ printColumnNames(FOS, SM);
+ FOS << '\n';
+ FOS.flush();
+
+ ArrayRef<llvm::MCInst> Source = getSource();
+ const unsigned Executions = LastInstructionIdx / Source.size() + 1;
+ for (unsigned I = 0, E = NumResourceUnits; I < E; ++I) {
+ double Usage = ResourceUsage[I + Source.size() * E];
+ printResourcePressure(FOS, Usage / Executions, (I + 1) * 7);
+ }
+
+ FOS.flush();
+ OS << Buffer;
+}
+
+void ResourcePressureView::printResourcePressurePerInst(raw_ostream &OS) const {
+ std::string Buffer;
+ raw_string_ostream TempStream(Buffer);
+ formatted_raw_ostream FOS(TempStream);
+
+ FOS << "\n\nResource pressure by instruction:\n";
+ printColumnNames(FOS, getSubTargetInfo().getSchedModel());
+ FOS << "Instructions:\n";
+
+ unsigned InstrIndex = 0;
+ ArrayRef<llvm::MCInst> Source = getSource();
+ const unsigned Executions = LastInstructionIdx / Source.size() + 1;
+ for (const MCInst &MCI : Source) {
+ unsigned BaseEltIdx = InstrIndex * NumResourceUnits;
+ for (unsigned J = 0; J < NumResourceUnits; ++J) {
+ double Usage = ResourceUsage[J + BaseEltIdx];
+ printResourcePressure(FOS, Usage / Executions, (J + 1) * 7);
+ }
+
+ FOS << printInstructionString(MCI) << '\n';
+ FOS.flush();
+ OS << Buffer;
+ Buffer = "";
+
+ ++InstrIndex;
+ }
+}
+
+json::Value ResourcePressureView::toJSON() const {
+ // We're dumping the instructions and the ResourceUsage array.
+ json::Array ResourcePressureInfo;
+
+ // The ResourceUsage matrix is sparse, so we only consider
+ // non-zero values.
+ ArrayRef<llvm::MCInst> Source = getSource();
+ const unsigned Executions = LastInstructionIdx / Source.size() + 1;
+ for (const auto &R : enumerate(ResourceUsage)) {
+ const ResourceCycles &RU = R.value();
+ if (RU.getNumerator() == 0)
+ continue;
+ unsigned InstructionIndex = R.index() / NumResourceUnits;
+ unsigned ResourceIndex = R.index() % NumResourceUnits;
+ double Usage = RU / Executions;
+ ResourcePressureInfo.push_back(
+ json::Object({{"InstructionIndex", InstructionIndex},
+ {"ResourceIndex", ResourceIndex},
+ {"ResourceUsage", Usage}}));
+ }
+
+ json::Object JO({{"ResourcePressureInfo", std::move(ResourcePressureInfo)}});
+ return JO;
+}
+} // namespace mca
+} // namespace llvm