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