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