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), TotalCycles(0), NumMicroOps(0), |
29 | ProcResourceUsage(Model.getNumProcResourceKinds(), 0), |
30 | ProcResourceMasks(Model.getNumProcResourceKinds()), |
31 | ResIdx2ProcResID(Model.getNumProcResourceKinds(), 0) { |
32 | computeProcResourceMasks(SM, Masks: ProcResourceMasks); |
33 | for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) { |
34 | unsigned Index = getResourceStateIndex(Mask: ProcResourceMasks[I]); |
35 | ResIdx2ProcResID[Index] = I; |
36 | } |
37 | } |
38 | |
39 | void SummaryView::onEvent(const HWInstructionEvent &Event) { |
40 | if (Event.Type == HWInstructionEvent::Dispatched) |
41 | LastInstructionIdx = Event.IR.getSourceIndex(); |
42 | |
43 | // We are only interested in the "instruction retired" events generated by |
44 | // the retire stage for instructions that are part of iteration #0. |
45 | if (Event.Type != HWInstructionEvent::Retired || |
46 | Event.IR.getSourceIndex() >= Source.size()) |
47 | return; |
48 | |
49 | // Update the cumulative number of resource cycles based on the processor |
50 | // resource usage information available from the instruction descriptor. We |
51 | // need to compute the cumulative number of resource cycles for every |
52 | // processor resource which is consumed by an instruction of the block. |
53 | const Instruction &Inst = *Event.IR.getInstruction(); |
54 | const InstrDesc &Desc = Inst.getDesc(); |
55 | NumMicroOps += Desc.NumMicroOps; |
56 | for (const std::pair<uint64_t, ResourceUsage> &RU : Desc.Resources) { |
57 | if (RU.second.size()) { |
58 | unsigned ProcResID = ResIdx2ProcResID[getResourceStateIndex(Mask: RU.first)]; |
59 | ProcResourceUsage[ProcResID] += RU.second.size(); |
60 | } |
61 | } |
62 | } |
63 | |
64 | void SummaryView::printView(raw_ostream &OS) const { |
65 | std::string Buffer; |
66 | raw_string_ostream TempStream(Buffer); |
67 | DisplayValues DV; |
68 | |
69 | collectData(DV); |
70 | TempStream << "Iterations: " << DV.Iterations; |
71 | TempStream << "\nInstructions: " << DV.TotalInstructions; |
72 | TempStream << "\nTotal Cycles: " << DV.TotalCycles; |
73 | TempStream << "\nTotal uOps: " << DV.TotalUOps << '\n'; |
74 | TempStream << "\nDispatch Width: " << DV.DispatchWidth; |
75 | TempStream << "\nuOps Per Cycle: " |
76 | << format(Fmt: "%.2f" , Vals: floor(x: (DV.UOpsPerCycle * 100) + 0.5) / 100); |
77 | TempStream << "\nIPC: " |
78 | << format(Fmt: "%.2f" , Vals: floor(x: (DV.IPC * 100) + 0.5) / 100); |
79 | TempStream << "\nBlock RThroughput: " |
80 | << format(Fmt: "%.1f" , Vals: floor(x: (DV.BlockRThroughput * 10) + 0.5) / 10) |
81 | << '\n'; |
82 | TempStream.flush(); |
83 | OS << Buffer; |
84 | } |
85 | |
86 | void SummaryView::collectData(DisplayValues &DV) const { |
87 | DV.Instructions = Source.size(); |
88 | DV.Iterations = (LastInstructionIdx / DV.Instructions) + 1; |
89 | DV.TotalInstructions = DV.Instructions * DV.Iterations; |
90 | DV.TotalCycles = TotalCycles; |
91 | DV.DispatchWidth = DispatchWidth; |
92 | DV.TotalUOps = NumMicroOps * DV.Iterations; |
93 | DV.UOpsPerCycle = (double)DV.TotalUOps / TotalCycles; |
94 | DV.IPC = (double)DV.TotalInstructions / TotalCycles; |
95 | DV.BlockRThroughput = computeBlockRThroughput(SM, DispatchWidth, NumMicroOps, |
96 | ProcResourceUsage); |
97 | } |
98 | |
99 | json::Value SummaryView::toJSON() const { |
100 | DisplayValues DV; |
101 | collectData(DV); |
102 | json::Object JO({{.K: "Iterations" , .V: DV.Iterations}, |
103 | {.K: "Instructions" , .V: DV.TotalInstructions}, |
104 | {.K: "TotalCycles" , .V: DV.TotalCycles}, |
105 | {.K: "TotaluOps" , .V: DV.TotalUOps}, |
106 | {.K: "DispatchWidth" , .V: DV.DispatchWidth}, |
107 | {.K: "uOpsPerCycle" , .V: DV.UOpsPerCycle}, |
108 | {.K: "IPC" , .V: DV.IPC}, |
109 | {.K: "BlockRThroughput" , .V: DV.BlockRThroughput}}); |
110 | return JO; |
111 | } |
112 | } // namespace mca. |
113 | } // namespace llvm |
114 | |