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 assert(Inst.getDefs().size() == 1 && "Expected a single definition!"); 64 assert(Inst.getUses().size() == 1 && "Expected a single register use!"); 65 const WriteState &WS = Inst.getDefs()[0]; 66 const ReadState &RS = Inst.getUses()[0]; 67 68 MoveEliminationInfo &Info = 69 MoveElimInfo[Inst.getDefs()[0].getRegisterFileID()]; 70 Info.TotalMoveEliminationCandidates++; 71 if (WS.isEliminated()) 72 Info.CurrentMovesEliminated++; 73 if (WS.isWriteZero() && RS.isReadZero()) 74 Info.TotalMovesThatPropagateZero++; 75 } 76 77 void RegisterFileStatistics::onEvent(const HWInstructionEvent &Event) { 78 switch (Event.Type) { 79 default: 80 break; 81 case HWInstructionEvent::Retired: { 82 const auto &RE = static_cast<const HWInstructionRetiredEvent &>(Event); 83 for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I) 84 PRFUsage[I].CurrentlyUsedMappings -= RE.FreedPhysRegs[I]; 85 break; 86 } 87 case HWInstructionEvent::Dispatched: { 88 const auto &DE = static_cast<const HWInstructionDispatchedEvent &>(Event); 89 updateRegisterFileUsage(DE.UsedPhysRegs); 90 updateMoveElimInfo(*DE.IR.getInstruction()); 91 } 92 } 93 } 94 95 void RegisterFileStatistics::onCycleEnd() { 96 for (MoveEliminationInfo &MEI : MoveElimInfo) { 97 unsigned &CurrentMax = MEI.MaxMovesEliminatedPerCycle; 98 CurrentMax = std::max(CurrentMax, MEI.CurrentMovesEliminated); 99 MEI.TotalMovesEliminated += MEI.CurrentMovesEliminated; 100 MEI.CurrentMovesEliminated = 0; 101 } 102 } 103 104 void RegisterFileStatistics::printView(raw_ostream &OS) const { 105 std::string Buffer; 106 raw_string_ostream TempStream(Buffer); 107 108 TempStream << "\n\nRegister File statistics:"; 109 const RegisterFileUsage &GlobalUsage = PRFUsage[0]; 110 TempStream << "\nTotal number of mappings created: " 111 << GlobalUsage.TotalMappings; 112 TempStream << "\nMax number of mappings used: " 113 << GlobalUsage.MaxUsedMappings << '\n'; 114 115 for (unsigned I = 1, E = PRFUsage.size(); I < E; ++I) { 116 const RegisterFileUsage &RFU = PRFUsage[I]; 117 // Obtain the register file descriptor from the scheduling model. 118 assert(STI.getSchedModel().hasExtraProcessorInfo() && 119 "Unable to find register file info!"); 120 const MCExtraProcessorInfo &PI = 121 STI.getSchedModel().getExtraProcessorInfo(); 122 assert(I <= PI.NumRegisterFiles && "Unexpected register file index!"); 123 const MCRegisterFileDesc &RFDesc = PI.RegisterFiles[I]; 124 // Skip invalid register files. 125 if (!RFDesc.NumPhysRegs) 126 continue; 127 128 TempStream << "\n* Register File #" << I; 129 TempStream << " -- " << StringRef(RFDesc.Name) << ':'; 130 TempStream << "\n Number of physical registers: "; 131 if (!RFDesc.NumPhysRegs) 132 TempStream << "unbounded"; 133 else 134 TempStream << RFDesc.NumPhysRegs; 135 TempStream << "\n Total number of mappings created: " 136 << RFU.TotalMappings; 137 TempStream << "\n Max number of mappings used: " 138 << RFU.MaxUsedMappings << '\n'; 139 const MoveEliminationInfo &MEI = MoveElimInfo[I]; 140 141 if (MEI.TotalMoveEliminationCandidates) { 142 TempStream << " Number of optimizable moves: " 143 << MEI.TotalMoveEliminationCandidates; 144 double EliminatedMovProportion = (double)MEI.TotalMovesEliminated / 145 MEI.TotalMoveEliminationCandidates * 146 100.0; 147 double ZeroMovProportion = (double)MEI.TotalMovesThatPropagateZero / 148 MEI.TotalMoveEliminationCandidates * 100.0; 149 TempStream << "\n Number of moves eliminated: " 150 << MEI.TotalMovesEliminated << " " 151 << format("(%.1f%%)", 152 floor((EliminatedMovProportion * 10) + 0.5) / 10); 153 TempStream << "\n Number of zero moves: " 154 << MEI.TotalMovesThatPropagateZero << " " 155 << format("(%.1f%%)", 156 floor((ZeroMovProportion * 10) + 0.5) / 10); 157 TempStream << "\n Max moves eliminated per cycle: " 158 << MEI.MaxMovesEliminatedPerCycle << '\n'; 159 } 160 } 161 162 TempStream.flush(); 163 OS << Buffer; 164 } 165 166 } // namespace mca 167 } // namespace llvm 168