1 //===--------------------- SummaryView.cpp -------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 ///
10 /// This file implements the functionalities used by the SummaryView to print
11 /// the report information.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "Views/SummaryView.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/MCA/Support.h"
18 #include "llvm/Support/Format.h"
19 
20 namespace llvm {
21 namespace mca {
22 
23 #define DEBUG_TYPE "llvm-mca"
24 
25 SummaryView::SummaryView(const MCSchedModel &Model, ArrayRef<MCInst> S,
26                          unsigned Width)
27     : SM(Model), Source(S), DispatchWidth(Width?Width: Model.IssueWidth),
28       LastInstructionIdx(0),
29       TotalCycles(0), NumMicroOps(0),
30       ProcResourceUsage(Model.getNumProcResourceKinds(), 0),
31       ProcResourceMasks(Model.getNumProcResourceKinds()),
32       ResIdx2ProcResID(Model.getNumProcResourceKinds(), 0) {
33   computeProcResourceMasks(SM, ProcResourceMasks);
34   for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) {
35     unsigned Index = getResourceStateIndex(ProcResourceMasks[I]);
36     ResIdx2ProcResID[Index] = I;
37   }
38 }
39 
40 void SummaryView::onEvent(const HWInstructionEvent &Event) {
41   if (Event.Type == HWInstructionEvent::Dispatched)
42     LastInstructionIdx = Event.IR.getSourceIndex();
43 
44   // We are only interested in the "instruction retired" events generated by
45   // the retire stage for instructions that are part of iteration #0.
46   if (Event.Type != HWInstructionEvent::Retired ||
47       Event.IR.getSourceIndex() >= Source.size())
48     return;
49 
50   // Update the cumulative number of resource cycles based on the processor
51   // resource usage information available from the instruction descriptor. We
52   // need to compute the cumulative number of resource cycles for every
53   // processor resource which is consumed by an instruction of the block.
54   const Instruction &Inst = *Event.IR.getInstruction();
55   const InstrDesc &Desc = Inst.getDesc();
56   NumMicroOps += Desc.NumMicroOps;
57   for (const std::pair<uint64_t, ResourceUsage> &RU : Desc.Resources) {
58     if (RU.second.size()) {
59       unsigned ProcResID = ResIdx2ProcResID[getResourceStateIndex(RU.first)];
60       ProcResourceUsage[ProcResID] += RU.second.size();
61     }
62   }
63 }
64 
65 void SummaryView::printView(raw_ostream &OS) const {
66   std::string Buffer;
67   raw_string_ostream TempStream(Buffer);
68   DisplayValues DV;
69 
70   collectData(DV);
71   TempStream << "Iterations:        " << DV.Iterations;
72   TempStream << "\nInstructions:      " << DV.TotalInstructions;
73   TempStream << "\nTotal Cycles:      " << DV.TotalCycles;
74   TempStream << "\nTotal uOps:        " << DV.TotalUOps << '\n';
75   TempStream << "\nDispatch Width:    " << DV.DispatchWidth;
76   TempStream << "\nuOps Per Cycle:    "
77              << format("%.2f", floor((DV.UOpsPerCycle * 100) + 0.5) / 100);
78   TempStream << "\nIPC:               "
79              << format("%.2f", floor((DV.IPC * 100) + 0.5) / 100);
80   TempStream << "\nBlock RThroughput: "
81              << format("%.1f", floor((DV.BlockRThroughput * 10) + 0.5) / 10)
82              << '\n';
83   TempStream.flush();
84   OS << Buffer;
85 }
86 
87 void SummaryView::collectData(DisplayValues &DV) const {
88   DV.Instructions = Source.size();
89   DV.Iterations = (LastInstructionIdx / DV.Instructions) + 1;
90   DV.TotalInstructions = DV.Instructions * DV.Iterations;
91   DV.TotalCycles = TotalCycles;
92   DV.DispatchWidth = DispatchWidth;
93   DV.TotalUOps = NumMicroOps * DV.Iterations;
94   DV.UOpsPerCycle = (double)DV.TotalUOps / TotalCycles;
95   DV.IPC = (double)DV.TotalInstructions / TotalCycles;
96   DV.BlockRThroughput = computeBlockRThroughput(SM, DispatchWidth, NumMicroOps,
97                                                 ProcResourceUsage);
98 }
99 
100 json::Value SummaryView::toJSON() const {
101   DisplayValues DV;
102   collectData(DV);
103   json::Object JO({{"Iterations", DV.Iterations},
104                    {"Instructions", DV.TotalInstructions},
105                    {"TotalCycles", DV.TotalCycles},
106                    {"TotaluOps", DV.TotalUOps},
107                    {"DispatchWidth", DV.DispatchWidth},
108                    {"uOpsPerCycle", DV.UOpsPerCycle},
109                    {"IPC", DV.IPC},
110                    {"BlockRThroughput", DV.BlockRThroughput}});
111   return JO;
112 }
113 } // namespace mca.
114 } // namespace llvm
115