| 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 | |