123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- //===--------------------- 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
|