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