diff options
author | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
---|---|---|
committer | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
commit | 06e5c21a835c0e923506c4ff27929f34e00761c2 (patch) | |
tree | 75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/libs/llvm12/tools/llvm-mca/Views/ResourcePressureView.cpp | |
parent | 03f024c4412e3aa613bb543cf1660176320ba8f4 (diff) | |
download | ydb-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.cpp | 200 |
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 |