1*0b57cec5SDimitry Andric //===--------------------- ResourcePressureView.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 methods in the ResourcePressureView interface. 11*0b57cec5SDimitry Andric /// 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include "Views/ResourcePressureView.h" 15*0b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h" 16*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 17*0b57cec5SDimitry Andric 18*0b57cec5SDimitry Andric namespace llvm { 19*0b57cec5SDimitry Andric namespace mca { 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric ResourcePressureView::ResourcePressureView(const llvm::MCSubtargetInfo &sti, 22*0b57cec5SDimitry Andric MCInstPrinter &Printer, 23*0b57cec5SDimitry Andric ArrayRef<MCInst> S) 24*0b57cec5SDimitry Andric : STI(sti), MCIP(Printer), Source(S), LastInstructionIdx(0) { 25*0b57cec5SDimitry Andric // Populate the map of resource descriptors. 26*0b57cec5SDimitry Andric unsigned R2VIndex = 0; 27*0b57cec5SDimitry Andric const MCSchedModel &SM = STI.getSchedModel(); 28*0b57cec5SDimitry Andric for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) { 29*0b57cec5SDimitry Andric const MCProcResourceDesc &ProcResource = *SM.getProcResource(I); 30*0b57cec5SDimitry Andric unsigned NumUnits = ProcResource.NumUnits; 31*0b57cec5SDimitry Andric // Skip groups and invalid resources with zero units. 32*0b57cec5SDimitry Andric if (ProcResource.SubUnitsIdxBegin || !NumUnits) 33*0b57cec5SDimitry Andric continue; 34*0b57cec5SDimitry Andric 35*0b57cec5SDimitry Andric Resource2VecIndex.insert(std::pair<unsigned, unsigned>(I, R2VIndex)); 36*0b57cec5SDimitry Andric R2VIndex += ProcResource.NumUnits; 37*0b57cec5SDimitry Andric } 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric NumResourceUnits = R2VIndex; 40*0b57cec5SDimitry Andric ResourceUsage.resize(NumResourceUnits * (Source.size() + 1)); 41*0b57cec5SDimitry Andric std::fill(ResourceUsage.begin(), ResourceUsage.end(), 0.0); 42*0b57cec5SDimitry Andric } 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric void ResourcePressureView::onEvent(const HWInstructionEvent &Event) { 45*0b57cec5SDimitry Andric if (Event.Type == HWInstructionEvent::Dispatched) { 46*0b57cec5SDimitry Andric LastInstructionIdx = Event.IR.getSourceIndex(); 47*0b57cec5SDimitry Andric return; 48*0b57cec5SDimitry Andric } 49*0b57cec5SDimitry Andric 50*0b57cec5SDimitry Andric // We're only interested in Issue events. 51*0b57cec5SDimitry Andric if (Event.Type != HWInstructionEvent::Issued) 52*0b57cec5SDimitry Andric return; 53*0b57cec5SDimitry Andric 54*0b57cec5SDimitry Andric const auto &IssueEvent = static_cast<const HWInstructionIssuedEvent &>(Event); 55*0b57cec5SDimitry Andric const unsigned SourceIdx = Event.IR.getSourceIndex() % Source.size(); 56*0b57cec5SDimitry Andric for (const std::pair<ResourceRef, ResourceCycles> &Use : 57*0b57cec5SDimitry Andric IssueEvent.UsedResources) { 58*0b57cec5SDimitry Andric const ResourceRef &RR = Use.first; 59*0b57cec5SDimitry Andric assert(Resource2VecIndex.find(RR.first) != Resource2VecIndex.end()); 60*0b57cec5SDimitry Andric unsigned R2VIndex = Resource2VecIndex[RR.first]; 61*0b57cec5SDimitry Andric R2VIndex += countTrailingZeros(RR.second); 62*0b57cec5SDimitry Andric ResourceUsage[R2VIndex + NumResourceUnits * SourceIdx] += Use.second; 63*0b57cec5SDimitry Andric ResourceUsage[R2VIndex + NumResourceUnits * Source.size()] += Use.second; 64*0b57cec5SDimitry Andric } 65*0b57cec5SDimitry Andric } 66*0b57cec5SDimitry Andric 67*0b57cec5SDimitry Andric static void printColumnNames(formatted_raw_ostream &OS, 68*0b57cec5SDimitry Andric const MCSchedModel &SM) { 69*0b57cec5SDimitry Andric unsigned Column = OS.getColumn(); 70*0b57cec5SDimitry Andric for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds(); 71*0b57cec5SDimitry Andric I < E; ++I) { 72*0b57cec5SDimitry Andric const MCProcResourceDesc &ProcResource = *SM.getProcResource(I); 73*0b57cec5SDimitry Andric unsigned NumUnits = ProcResource.NumUnits; 74*0b57cec5SDimitry Andric // Skip groups and invalid resources with zero units. 75*0b57cec5SDimitry Andric if (ProcResource.SubUnitsIdxBegin || !NumUnits) 76*0b57cec5SDimitry Andric continue; 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric for (unsigned J = 0; J < NumUnits; ++J) { 79*0b57cec5SDimitry Andric Column += 7; 80*0b57cec5SDimitry Andric OS << "[" << ResourceIndex; 81*0b57cec5SDimitry Andric if (NumUnits > 1) 82*0b57cec5SDimitry Andric OS << '.' << J; 83*0b57cec5SDimitry Andric OS << ']'; 84*0b57cec5SDimitry Andric OS.PadToColumn(Column); 85*0b57cec5SDimitry Andric } 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric ResourceIndex++; 88*0b57cec5SDimitry Andric } 89*0b57cec5SDimitry Andric } 90*0b57cec5SDimitry Andric 91*0b57cec5SDimitry Andric static void printResourcePressure(formatted_raw_ostream &OS, double Pressure, 92*0b57cec5SDimitry Andric unsigned Col) { 93*0b57cec5SDimitry Andric if (!Pressure || Pressure < 0.005) { 94*0b57cec5SDimitry Andric OS << " - "; 95*0b57cec5SDimitry Andric } else { 96*0b57cec5SDimitry Andric // Round to the value to the nearest hundredth and then print it. 97*0b57cec5SDimitry Andric OS << format("%.2f", floor((Pressure * 100) + 0.5) / 100); 98*0b57cec5SDimitry Andric } 99*0b57cec5SDimitry Andric OS.PadToColumn(Col); 100*0b57cec5SDimitry Andric } 101*0b57cec5SDimitry Andric 102*0b57cec5SDimitry Andric void ResourcePressureView::printResourcePressurePerIter(raw_ostream &OS) const { 103*0b57cec5SDimitry Andric std::string Buffer; 104*0b57cec5SDimitry Andric raw_string_ostream TempStream(Buffer); 105*0b57cec5SDimitry Andric formatted_raw_ostream FOS(TempStream); 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric FOS << "\n\nResources:\n"; 108*0b57cec5SDimitry Andric const MCSchedModel &SM = STI.getSchedModel(); 109*0b57cec5SDimitry Andric for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds(); 110*0b57cec5SDimitry Andric I < E; ++I) { 111*0b57cec5SDimitry Andric const MCProcResourceDesc &ProcResource = *SM.getProcResource(I); 112*0b57cec5SDimitry Andric unsigned NumUnits = ProcResource.NumUnits; 113*0b57cec5SDimitry Andric // Skip groups and invalid resources with zero units. 114*0b57cec5SDimitry Andric if (ProcResource.SubUnitsIdxBegin || !NumUnits) 115*0b57cec5SDimitry Andric continue; 116*0b57cec5SDimitry Andric 117*0b57cec5SDimitry Andric for (unsigned J = 0; J < NumUnits; ++J) { 118*0b57cec5SDimitry Andric FOS << '[' << ResourceIndex; 119*0b57cec5SDimitry Andric if (NumUnits > 1) 120*0b57cec5SDimitry Andric FOS << '.' << J; 121*0b57cec5SDimitry Andric FOS << ']'; 122*0b57cec5SDimitry Andric FOS.PadToColumn(6); 123*0b57cec5SDimitry Andric FOS << "- " << ProcResource.Name << '\n'; 124*0b57cec5SDimitry Andric } 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric ResourceIndex++; 127*0b57cec5SDimitry Andric } 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric FOS << "\n\nResource pressure per iteration:\n"; 130*0b57cec5SDimitry Andric FOS.flush(); 131*0b57cec5SDimitry Andric printColumnNames(FOS, SM); 132*0b57cec5SDimitry Andric FOS << '\n'; 133*0b57cec5SDimitry Andric FOS.flush(); 134*0b57cec5SDimitry Andric 135*0b57cec5SDimitry Andric const unsigned Executions = LastInstructionIdx / Source.size() + 1; 136*0b57cec5SDimitry Andric for (unsigned I = 0, E = NumResourceUnits; I < E; ++I) { 137*0b57cec5SDimitry Andric double Usage = ResourceUsage[I + Source.size() * E]; 138*0b57cec5SDimitry Andric printResourcePressure(FOS, Usage / Executions, (I + 1) * 7); 139*0b57cec5SDimitry Andric } 140*0b57cec5SDimitry Andric 141*0b57cec5SDimitry Andric FOS.flush(); 142*0b57cec5SDimitry Andric OS << Buffer; 143*0b57cec5SDimitry Andric } 144*0b57cec5SDimitry Andric 145*0b57cec5SDimitry Andric void ResourcePressureView::printResourcePressurePerInst(raw_ostream &OS) const { 146*0b57cec5SDimitry Andric std::string Buffer; 147*0b57cec5SDimitry Andric raw_string_ostream TempStream(Buffer); 148*0b57cec5SDimitry Andric formatted_raw_ostream FOS(TempStream); 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric FOS << "\n\nResource pressure by instruction:\n"; 151*0b57cec5SDimitry Andric printColumnNames(FOS, STI.getSchedModel()); 152*0b57cec5SDimitry Andric FOS << "Instructions:\n"; 153*0b57cec5SDimitry Andric 154*0b57cec5SDimitry Andric std::string Instruction; 155*0b57cec5SDimitry Andric raw_string_ostream InstrStream(Instruction); 156*0b57cec5SDimitry Andric 157*0b57cec5SDimitry Andric unsigned InstrIndex = 0; 158*0b57cec5SDimitry Andric const unsigned Executions = LastInstructionIdx / Source.size() + 1; 159*0b57cec5SDimitry Andric for (const MCInst &MCI : Source) { 160*0b57cec5SDimitry Andric unsigned BaseEltIdx = InstrIndex * NumResourceUnits; 161*0b57cec5SDimitry Andric for (unsigned J = 0; J < NumResourceUnits; ++J) { 162*0b57cec5SDimitry Andric double Usage = ResourceUsage[J + BaseEltIdx]; 163*0b57cec5SDimitry Andric printResourcePressure(FOS, Usage / Executions, (J + 1) * 7); 164*0b57cec5SDimitry Andric } 165*0b57cec5SDimitry Andric 166*0b57cec5SDimitry Andric MCIP.printInst(&MCI, InstrStream, "", STI); 167*0b57cec5SDimitry Andric InstrStream.flush(); 168*0b57cec5SDimitry Andric StringRef Str(Instruction); 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric // Remove any tabs or spaces at the beginning of the instruction. 171*0b57cec5SDimitry Andric Str = Str.ltrim(); 172*0b57cec5SDimitry Andric 173*0b57cec5SDimitry Andric FOS << Str << '\n'; 174*0b57cec5SDimitry Andric Instruction = ""; 175*0b57cec5SDimitry Andric 176*0b57cec5SDimitry Andric FOS.flush(); 177*0b57cec5SDimitry Andric OS << Buffer; 178*0b57cec5SDimitry Andric Buffer = ""; 179*0b57cec5SDimitry Andric 180*0b57cec5SDimitry Andric ++InstrIndex; 181*0b57cec5SDimitry Andric } 182*0b57cec5SDimitry Andric } 183*0b57cec5SDimitry Andric } // namespace mca 184*0b57cec5SDimitry Andric } // namespace llvm 185