xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-mca/Views/SummaryView.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
1*fe6060f1SDimitry Andric //===--------------------- SummaryView.cpp ----------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric ///
100b57cec5SDimitry Andric /// This file implements the functionalities used by the SummaryView to print
110b57cec5SDimitry Andric /// the report information.
120b57cec5SDimitry Andric ///
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "Views/SummaryView.h"
160b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
170b57cec5SDimitry Andric #include "llvm/MCA/Support.h"
180b57cec5SDimitry Andric #include "llvm/Support/Format.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric namespace llvm {
210b57cec5SDimitry Andric namespace mca {
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #define DEBUG_TYPE "llvm-mca"
240b57cec5SDimitry Andric 
SummaryView(const MCSchedModel & Model,ArrayRef<MCInst> S,unsigned Width)250b57cec5SDimitry Andric SummaryView::SummaryView(const MCSchedModel &Model, ArrayRef<MCInst> S,
260b57cec5SDimitry Andric                          unsigned Width)
270b57cec5SDimitry Andric     : SM(Model), Source(S), DispatchWidth(Width ? Width : Model.IssueWidth),
28*fe6060f1SDimitry Andric       LastInstructionIdx(0), TotalCycles(0), NumMicroOps(0),
290b57cec5SDimitry Andric       ProcResourceUsage(Model.getNumProcResourceKinds(), 0),
300b57cec5SDimitry Andric       ProcResourceMasks(Model.getNumProcResourceKinds()),
310b57cec5SDimitry Andric       ResIdx2ProcResID(Model.getNumProcResourceKinds(), 0) {
320b57cec5SDimitry Andric   computeProcResourceMasks(SM, ProcResourceMasks);
330b57cec5SDimitry Andric   for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) {
340b57cec5SDimitry Andric     unsigned Index = getResourceStateIndex(ProcResourceMasks[I]);
350b57cec5SDimitry Andric     ResIdx2ProcResID[Index] = I;
360b57cec5SDimitry Andric   }
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric 
onEvent(const HWInstructionEvent & Event)390b57cec5SDimitry Andric void SummaryView::onEvent(const HWInstructionEvent &Event) {
400b57cec5SDimitry Andric   if (Event.Type == HWInstructionEvent::Dispatched)
410b57cec5SDimitry Andric     LastInstructionIdx = Event.IR.getSourceIndex();
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   // We are only interested in the "instruction retired" events generated by
440b57cec5SDimitry Andric   // the retire stage for instructions that are part of iteration #0.
450b57cec5SDimitry Andric   if (Event.Type != HWInstructionEvent::Retired ||
460b57cec5SDimitry Andric       Event.IR.getSourceIndex() >= Source.size())
470b57cec5SDimitry Andric     return;
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   // Update the cumulative number of resource cycles based on the processor
500b57cec5SDimitry Andric   // resource usage information available from the instruction descriptor. We
510b57cec5SDimitry Andric   // need to compute the cumulative number of resource cycles for every
520b57cec5SDimitry Andric   // processor resource which is consumed by an instruction of the block.
530b57cec5SDimitry Andric   const Instruction &Inst = *Event.IR.getInstruction();
540b57cec5SDimitry Andric   const InstrDesc &Desc = Inst.getDesc();
550b57cec5SDimitry Andric   NumMicroOps += Desc.NumMicroOps;
56480093f4SDimitry Andric   for (const std::pair<uint64_t, ResourceUsage> &RU : Desc.Resources) {
570b57cec5SDimitry Andric     if (RU.second.size()) {
580b57cec5SDimitry Andric       unsigned ProcResID = ResIdx2ProcResID[getResourceStateIndex(RU.first)];
590b57cec5SDimitry Andric       ProcResourceUsage[ProcResID] += RU.second.size();
600b57cec5SDimitry Andric     }
610b57cec5SDimitry Andric   }
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
printView(raw_ostream & OS) const640b57cec5SDimitry Andric void SummaryView::printView(raw_ostream &OS) const {
650b57cec5SDimitry Andric   std::string Buffer;
660b57cec5SDimitry Andric   raw_string_ostream TempStream(Buffer);
67e8d8bef9SDimitry Andric   DisplayValues DV;
68e8d8bef9SDimitry Andric 
69e8d8bef9SDimitry Andric   collectData(DV);
70e8d8bef9SDimitry Andric   TempStream << "Iterations:        " << DV.Iterations;
71e8d8bef9SDimitry Andric   TempStream << "\nInstructions:      " << DV.TotalInstructions;
72e8d8bef9SDimitry Andric   TempStream << "\nTotal Cycles:      " << DV.TotalCycles;
73e8d8bef9SDimitry Andric   TempStream << "\nTotal uOps:        " << DV.TotalUOps << '\n';
74e8d8bef9SDimitry Andric   TempStream << "\nDispatch Width:    " << DV.DispatchWidth;
750b57cec5SDimitry Andric   TempStream << "\nuOps Per Cycle:    "
76e8d8bef9SDimitry Andric              << format("%.2f", floor((DV.UOpsPerCycle * 100) + 0.5) / 100);
770b57cec5SDimitry Andric   TempStream << "\nIPC:               "
78e8d8bef9SDimitry Andric              << format("%.2f", floor((DV.IPC * 100) + 0.5) / 100);
790b57cec5SDimitry Andric   TempStream << "\nBlock RThroughput: "
80e8d8bef9SDimitry Andric              << format("%.1f", floor((DV.BlockRThroughput * 10) + 0.5) / 10)
810b57cec5SDimitry Andric              << '\n';
820b57cec5SDimitry Andric   TempStream.flush();
830b57cec5SDimitry Andric   OS << Buffer;
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric 
collectData(DisplayValues & DV) const86e8d8bef9SDimitry Andric void SummaryView::collectData(DisplayValues &DV) const {
87e8d8bef9SDimitry Andric   DV.Instructions = Source.size();
88e8d8bef9SDimitry Andric   DV.Iterations = (LastInstructionIdx / DV.Instructions) + 1;
89e8d8bef9SDimitry Andric   DV.TotalInstructions = DV.Instructions * DV.Iterations;
90e8d8bef9SDimitry Andric   DV.TotalCycles = TotalCycles;
91e8d8bef9SDimitry Andric   DV.DispatchWidth = DispatchWidth;
92e8d8bef9SDimitry Andric   DV.TotalUOps = NumMicroOps * DV.Iterations;
93e8d8bef9SDimitry Andric   DV.UOpsPerCycle = (double)DV.TotalUOps / TotalCycles;
94e8d8bef9SDimitry Andric   DV.IPC = (double)DV.TotalInstructions / TotalCycles;
95e8d8bef9SDimitry Andric   DV.BlockRThroughput = computeBlockRThroughput(SM, DispatchWidth, NumMicroOps,
96e8d8bef9SDimitry Andric                                                 ProcResourceUsage);
97e8d8bef9SDimitry Andric }
98e8d8bef9SDimitry Andric 
toJSON() const99e8d8bef9SDimitry Andric json::Value SummaryView::toJSON() const {
100e8d8bef9SDimitry Andric   DisplayValues DV;
101e8d8bef9SDimitry Andric   collectData(DV);
102e8d8bef9SDimitry Andric   json::Object JO({{"Iterations", DV.Iterations},
103e8d8bef9SDimitry Andric                    {"Instructions", DV.TotalInstructions},
104e8d8bef9SDimitry Andric                    {"TotalCycles", DV.TotalCycles},
105e8d8bef9SDimitry Andric                    {"TotaluOps", DV.TotalUOps},
106e8d8bef9SDimitry Andric                    {"DispatchWidth", DV.DispatchWidth},
107e8d8bef9SDimitry Andric                    {"uOpsPerCycle", DV.UOpsPerCycle},
108e8d8bef9SDimitry Andric                    {"IPC", DV.IPC},
109e8d8bef9SDimitry Andric                    {"BlockRThroughput", DV.BlockRThroughput}});
110e8d8bef9SDimitry Andric   return JO;
111e8d8bef9SDimitry Andric }
1120b57cec5SDimitry Andric } // namespace mca.
1130b57cec5SDimitry Andric } // namespace llvm
114