1 //===--------------------- RegisterFileStatistics.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 RegisterFileStatistics interface. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "Views/RegisterFileStatistics.h" 15 #include "llvm/Support/Format.h" 16 17 namespace llvm { 18 namespace mca { 19 20 RegisterFileStatistics::RegisterFileStatistics(const MCSubtargetInfo &sti) 21 : STI(sti) { 22 const MCSchedModel &SM = STI.getSchedModel(); 23 RegisterFileUsage RFUEmpty = {0, 0, 0}; 24 MoveEliminationInfo MEIEmpty = {0, 0, 0, 0, 0}; 25 if (!SM.hasExtraProcessorInfo()) { 26 // Assume a single register file. 27 PRFUsage.emplace_back(RFUEmpty); 28 MoveElimInfo.emplace_back(MEIEmpty); 29 return; 30 } 31 32 // Initialize a RegisterFileUsage for every user defined register file, plus 33 // the default register file which is always at index #0. 34 const MCExtraProcessorInfo &PI = SM.getExtraProcessorInfo(); 35 // There is always an "InvalidRegisterFile" entry in tablegen. That entry can 36 // be skipped. If there are no user defined register files, then reserve a 37 // single entry for the default register file at index #0. 38 unsigned NumRegFiles = std::max(PI.NumRegisterFiles, 1U); 39 40 PRFUsage.resize(NumRegFiles); 41 std::fill(PRFUsage.begin(), PRFUsage.end(), RFUEmpty); 42 43 MoveElimInfo.resize(NumRegFiles); 44 std::fill(MoveElimInfo.begin(), MoveElimInfo.end(), MEIEmpty); 45 } 46 47 void RegisterFileStatistics::updateRegisterFileUsage( 48 ArrayRef<unsigned> UsedPhysRegs) { 49 for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I) { 50 RegisterFileUsage &RFU = PRFUsage[I]; 51 unsigned NumUsedPhysRegs = UsedPhysRegs[I]; 52 RFU.CurrentlyUsedMappings += NumUsedPhysRegs; 53 RFU.TotalMappings += NumUsedPhysRegs; 54 RFU.MaxUsedMappings = 55 std::max(RFU.MaxUsedMappings, RFU.CurrentlyUsedMappings); 56 } 57 } 58 59 void RegisterFileStatistics::updateMoveElimInfo(const Instruction &Inst) { 60 if (!Inst.isOptimizableMove()) 61 return; 62 63 if (Inst.getDefs().size() != Inst.getUses().size()) 64 return; 65 66 for (size_t I = 0, E = Inst.getDefs().size(); I < E; ++I) { 67 const WriteState &WS = Inst.getDefs()[I]; 68 const ReadState &RS = Inst.getUses()[E - (I + 1)]; 69 70 MoveEliminationInfo &Info = 71 MoveElimInfo[Inst.getDefs()[0].getRegisterFileID()]; 72 Info.TotalMoveEliminationCandidates++; 73 if (WS.isEliminated()) 74 Info.CurrentMovesEliminated++; 75 if (WS.isWriteZero() && RS.isReadZero()) 76 Info.TotalMovesThatPropagateZero++; 77 } 78 } 79 80 void RegisterFileStatistics::onEvent(const HWInstructionEvent &Event) { 81 switch (Event.Type) { 82 default: 83 break; 84 case HWInstructionEvent::Retired: { 85 const auto &RE = static_cast<const HWInstructionRetiredEvent &>(Event); 86 for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I) 87 PRFUsage[I].CurrentlyUsedMappings -= RE.FreedPhysRegs[I]; 88 break; 89 } 90 case HWInstructionEvent::Dispatched: { 91 const auto &DE = static_cast<const HWInstructionDispatchedEvent &>(Event); 92 updateRegisterFileUsage(DE.UsedPhysRegs); 93 updateMoveElimInfo(*DE.IR.getInstruction()); 94 } 95 } 96 } 97 98 void RegisterFileStatistics::onCycleEnd() { 99 for (MoveEliminationInfo &MEI : MoveElimInfo) { 100 unsigned &CurrentMax = MEI.MaxMovesEliminatedPerCycle; 101 CurrentMax = std::max(CurrentMax, MEI.CurrentMovesEliminated); 102 MEI.TotalMovesEliminated += MEI.CurrentMovesEliminated; 103 MEI.CurrentMovesEliminated = 0; 104 } 105 } 106 107 void RegisterFileStatistics::printView(raw_ostream &OS) const { 108 std::string Buffer; 109 raw_string_ostream TempStream(Buffer); 110 111 TempStream << "\n\nRegister File statistics:"; 112 const RegisterFileUsage &GlobalUsage = PRFUsage[0]; 113 TempStream << "\nTotal number of mappings created: " 114 << GlobalUsage.TotalMappings; 115 TempStream << "\nMax number of mappings used: " 116 << GlobalUsage.MaxUsedMappings << '\n'; 117 118 for (unsigned I = 1, E = PRFUsage.size(); I < E; ++I) { 119 const RegisterFileUsage &RFU = PRFUsage[I]; 120 // Obtain the register file descriptor from the scheduling model. 121 assert(STI.getSchedModel().hasExtraProcessorInfo() && 122 "Unable to find register file info!"); 123 const MCExtraProcessorInfo &PI = 124 STI.getSchedModel().getExtraProcessorInfo(); 125 assert(I <= PI.NumRegisterFiles && "Unexpected register file index!"); 126 const MCRegisterFileDesc &RFDesc = PI.RegisterFiles[I]; 127 // Skip invalid register files. 128 if (!RFDesc.NumPhysRegs) 129 continue; 130 131 TempStream << "\n* Register File #" << I; 132 TempStream << " -- " << StringRef(RFDesc.Name) << ':'; 133 TempStream << "\n Number of physical registers: "; 134 if (!RFDesc.NumPhysRegs) 135 TempStream << "unbounded"; 136 else 137 TempStream << RFDesc.NumPhysRegs; 138 TempStream << "\n Total number of mappings created: " 139 << RFU.TotalMappings; 140 TempStream << "\n Max number of mappings used: " 141 << RFU.MaxUsedMappings << '\n'; 142 const MoveEliminationInfo &MEI = MoveElimInfo[I]; 143 144 if (MEI.TotalMoveEliminationCandidates) { 145 TempStream << " Number of optimizable moves: " 146 << MEI.TotalMoveEliminationCandidates; 147 double EliminatedMovProportion = (double)MEI.TotalMovesEliminated / 148 MEI.TotalMoveEliminationCandidates * 149 100.0; 150 double ZeroMovProportion = (double)MEI.TotalMovesThatPropagateZero / 151 MEI.TotalMoveEliminationCandidates * 100.0; 152 TempStream << "\n Number of moves eliminated: " 153 << MEI.TotalMovesEliminated << " " 154 << format("(%.1f%%)", 155 floor((EliminatedMovProportion * 10) + 0.5) / 10); 156 TempStream << "\n Number of zero moves: " 157 << MEI.TotalMovesThatPropagateZero << " " 158 << format("(%.1f%%)", 159 floor((ZeroMovProportion * 10) + 0.5) / 10); 160 TempStream << "\n Max moves eliminated per cycle: " 161 << MEI.MaxMovesEliminatedPerCycle << '\n'; 162 } 163 } 164 165 TempStream.flush(); 166 OS << Buffer; 167 } 168 169 } // namespace mca 170 } // namespace llvm 171