Path: blob/main/contrib/llvm-project/llvm/tools/llvm-mca/Views/SchedulerStatistics.cpp
35290 views
//===--------------------- SchedulerStatistics.cpp --------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8///9/// This file implements the SchedulerStatistics interface.10///11//===----------------------------------------------------------------------===//1213#include "Views/SchedulerStatistics.h"14#include "llvm/Support/Format.h"15#include "llvm/Support/FormattedStream.h"1617namespace llvm {18namespace mca {1920SchedulerStatistics::SchedulerStatistics(const llvm::MCSubtargetInfo &STI)21: SM(STI.getSchedModel()), LQResourceID(0), SQResourceID(0), NumIssued(0),22NumCycles(0), MostRecentLoadDispatched(~0U),23MostRecentStoreDispatched(~0U),24Usage(STI.getSchedModel().NumProcResourceKinds, {0, 0, 0}) {25if (SM.hasExtraProcessorInfo()) {26const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();27LQResourceID = EPI.LoadQueueID;28SQResourceID = EPI.StoreQueueID;29}30}3132// FIXME: This implementation works under the assumption that load/store queue33// entries are reserved at 'instruction dispatched' stage, and released at34// 'instruction executed' stage. This currently matches the behavior of LSUnit.35//36// The current design minimizes the number of events generated by the37// Dispatch/Execute stages, at the cost of doing extra bookkeeping in method38// `onEvent`. However, it introduces a subtle dependency between this view and39// how the LSUnit works.40//41// In future we should add a new "memory queue" event type, so that we stop42// making assumptions on how LSUnit internally works (See PR39828).43void SchedulerStatistics::onEvent(const HWInstructionEvent &Event) {44if (Event.Type == HWInstructionEvent::Issued) {45const Instruction &Inst = *Event.IR.getInstruction();46NumIssued += Inst.getDesc().NumMicroOps;47} else if (Event.Type == HWInstructionEvent::Dispatched) {48const Instruction &Inst = *Event.IR.getInstruction();49const unsigned Index = Event.IR.getSourceIndex();50if (LQResourceID && Inst.getMayLoad() &&51MostRecentLoadDispatched != Index) {52Usage[LQResourceID].SlotsInUse++;53MostRecentLoadDispatched = Index;54}55if (SQResourceID && Inst.getMayStore() &&56MostRecentStoreDispatched != Index) {57Usage[SQResourceID].SlotsInUse++;58MostRecentStoreDispatched = Index;59}60} else if (Event.Type == HWInstructionEvent::Executed) {61const Instruction &Inst = *Event.IR.getInstruction();62if (LQResourceID && Inst.getMayLoad()) {63assert(Usage[LQResourceID].SlotsInUse);64Usage[LQResourceID].SlotsInUse--;65}66if (SQResourceID && Inst.getMayStore()) {67assert(Usage[SQResourceID].SlotsInUse);68Usage[SQResourceID].SlotsInUse--;69}70}71}7273void SchedulerStatistics::onReservedBuffers(const InstRef & /* unused */,74ArrayRef<unsigned> Buffers) {75for (const unsigned Buffer : Buffers) {76if (Buffer == LQResourceID || Buffer == SQResourceID)77continue;78Usage[Buffer].SlotsInUse++;79}80}8182void SchedulerStatistics::onReleasedBuffers(const InstRef & /* unused */,83ArrayRef<unsigned> Buffers) {84for (const unsigned Buffer : Buffers) {85if (Buffer == LQResourceID || Buffer == SQResourceID)86continue;87Usage[Buffer].SlotsInUse--;88}89}9091void SchedulerStatistics::updateHistograms() {92for (BufferUsage &BU : Usage) {93BU.CumulativeNumUsedSlots += BU.SlotsInUse;94BU.MaxUsedSlots = std::max(BU.MaxUsedSlots, BU.SlotsInUse);95}9697IssueWidthPerCycle[NumIssued]++;98NumIssued = 0;99}100101void SchedulerStatistics::printSchedulerStats(raw_ostream &OS) const {102OS << "\n\nSchedulers - "103<< "number of cycles where we saw N micro opcodes issued:\n";104OS << "[# issued], [# cycles]\n";105106bool HasColors = OS.has_colors();107const auto It = llvm::max_element(IssueWidthPerCycle);108for (const std::pair<const unsigned, unsigned> &Entry : IssueWidthPerCycle) {109unsigned NumIssued = Entry.first;110if (NumIssued == It->first && HasColors)111OS.changeColor(raw_ostream::SAVEDCOLOR, true, false);112113unsigned IPC = Entry.second;114OS << " " << NumIssued << ", " << IPC << " ("115<< format("%.1f", ((double)IPC / NumCycles) * 100) << "%)\n";116if (HasColors)117OS.resetColor();118}119}120121void SchedulerStatistics::printSchedulerUsage(raw_ostream &OS) const {122assert(NumCycles && "Unexpected number of cycles!");123124OS << "\nScheduler's queue usage:\n";125if (all_of(Usage, [](const BufferUsage &BU) { return !BU.MaxUsedSlots; })) {126OS << "No scheduler resources used.\n";127return;128}129130OS << "[1] Resource name.\n"131<< "[2] Average number of used buffer entries.\n"132<< "[3] Maximum number of used buffer entries.\n"133<< "[4] Total number of buffer entries.\n\n"134<< " [1] [2] [3] [4]\n";135136formatted_raw_ostream FOS(OS);137bool HasColors = FOS.has_colors();138for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {139const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);140if (ProcResource.BufferSize <= 0)141continue;142143const BufferUsage &BU = Usage[I];144double AvgUsage = (double)BU.CumulativeNumUsedSlots / NumCycles;145double AlmostFullThreshold = (double)(ProcResource.BufferSize * 4) / 5;146unsigned NormalizedAvg = floor((AvgUsage * 10) + 0.5) / 10;147unsigned NormalizedThreshold = floor((AlmostFullThreshold * 10) + 0.5) / 10;148149FOS << ProcResource.Name;150FOS.PadToColumn(17);151if (HasColors && NormalizedAvg >= NormalizedThreshold)152FOS.changeColor(raw_ostream::YELLOW, true, false);153FOS << NormalizedAvg;154if (HasColors)155FOS.resetColor();156FOS.PadToColumn(28);157if (HasColors &&158BU.MaxUsedSlots == static_cast<unsigned>(ProcResource.BufferSize))159FOS.changeColor(raw_ostream::RED, true, false);160FOS << BU.MaxUsedSlots;161if (HasColors)162FOS.resetColor();163FOS.PadToColumn(39);164FOS << ProcResource.BufferSize << '\n';165}166167FOS.flush();168}169170void SchedulerStatistics::printView(raw_ostream &OS) const {171printSchedulerStats(OS);172printSchedulerUsage(OS);173}174175} // namespace mca176} // namespace llvm177178179