171 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8/// \file9///10/// This file implements the RegisterFileStatistics interface.11///12//===----------------------------------------------------------------------===//13 14#include "Views/RegisterFileStatistics.h"15#include "llvm/Support/Format.h"16 17namespace llvm {18namespace mca {19 20RegisterFileStatistics::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, plus33 // 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 can36 // be skipped. If there are no user defined register files, then reserve a37 // single entry for the default register file at index #0.38 unsigned NumRegFiles = std::max(PI.NumRegisterFiles, 1U);39 40 PRFUsage.resize(NumRegFiles);41 llvm::fill(PRFUsage, RFUEmpty);42 43 MoveElimInfo.resize(NumRegFiles);44 llvm::fill(MoveElimInfo, MEIEmpty);45}46 47void 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 59void 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 80void 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 98void 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 107void 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 else137 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 mca170} // namespace llvm171