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