Path: blob/main/contrib/llvm-project/llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp
96353 views
//===--------------------- RegisterFileStatistics.cpp -----------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8///9/// This file implements the RegisterFileStatistics interface.10///11//===----------------------------------------------------------------------===//1213#include "Views/RegisterFileStatistics.h"14#include "llvm/Support/Format.h"1516namespace llvm {17namespace mca {1819RegisterFileStatistics::RegisterFileStatistics(const MCSubtargetInfo &sti)20: STI(sti) {21const MCSchedModel &SM = STI.getSchedModel();22RegisterFileUsage RFUEmpty = {0, 0, 0};23MoveEliminationInfo MEIEmpty = {0, 0, 0, 0, 0};24if (!SM.hasExtraProcessorInfo()) {25// Assume a single register file.26PRFUsage.emplace_back(RFUEmpty);27MoveElimInfo.emplace_back(MEIEmpty);28return;29}3031// Initialize a RegisterFileUsage for every user defined register file, plus32// the default register file which is always at index #0.33const MCExtraProcessorInfo &PI = SM.getExtraProcessorInfo();34// There is always an "InvalidRegisterFile" entry in tablegen. That entry can35// be skipped. If there are no user defined register files, then reserve a36// single entry for the default register file at index #0.37unsigned NumRegFiles = std::max(PI.NumRegisterFiles, 1U);3839PRFUsage.resize(NumRegFiles);40std::fill(PRFUsage.begin(), PRFUsage.end(), RFUEmpty);4142MoveElimInfo.resize(NumRegFiles);43std::fill(MoveElimInfo.begin(), MoveElimInfo.end(), MEIEmpty);44}4546void RegisterFileStatistics::updateRegisterFileUsage(47ArrayRef<unsigned> UsedPhysRegs) {48for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I) {49RegisterFileUsage &RFU = PRFUsage[I];50unsigned NumUsedPhysRegs = UsedPhysRegs[I];51RFU.CurrentlyUsedMappings += NumUsedPhysRegs;52RFU.TotalMappings += NumUsedPhysRegs;53RFU.MaxUsedMappings =54std::max(RFU.MaxUsedMappings, RFU.CurrentlyUsedMappings);55}56}5758void RegisterFileStatistics::updateMoveElimInfo(const Instruction &Inst) {59if (!Inst.isOptimizableMove())60return;6162if (Inst.getDefs().size() != Inst.getUses().size())63return;6465for (size_t I = 0, E = Inst.getDefs().size(); I < E; ++I) {66const WriteState &WS = Inst.getDefs()[I];67const ReadState &RS = Inst.getUses()[E - (I + 1)];6869MoveEliminationInfo &Info =70MoveElimInfo[Inst.getDefs()[0].getRegisterFileID()];71Info.TotalMoveEliminationCandidates++;72if (WS.isEliminated())73Info.CurrentMovesEliminated++;74if (WS.isWriteZero() && RS.isReadZero())75Info.TotalMovesThatPropagateZero++;76}77}7879void RegisterFileStatistics::onEvent(const HWInstructionEvent &Event) {80switch (Event.Type) {81default:82break;83case HWInstructionEvent::Retired: {84const auto &RE = static_cast<const HWInstructionRetiredEvent &>(Event);85for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I)86PRFUsage[I].CurrentlyUsedMappings -= RE.FreedPhysRegs[I];87break;88}89case HWInstructionEvent::Dispatched: {90const auto &DE = static_cast<const HWInstructionDispatchedEvent &>(Event);91updateRegisterFileUsage(DE.UsedPhysRegs);92updateMoveElimInfo(*DE.IR.getInstruction());93}94}95}9697void RegisterFileStatistics::onCycleEnd() {98for (MoveEliminationInfo &MEI : MoveElimInfo) {99unsigned &CurrentMax = MEI.MaxMovesEliminatedPerCycle;100CurrentMax = std::max(CurrentMax, MEI.CurrentMovesEliminated);101MEI.TotalMovesEliminated += MEI.CurrentMovesEliminated;102MEI.CurrentMovesEliminated = 0;103}104}105106void RegisterFileStatistics::printView(raw_ostream &OS) const {107std::string Buffer;108raw_string_ostream TempStream(Buffer);109110TempStream << "\n\nRegister File statistics:";111const RegisterFileUsage &GlobalUsage = PRFUsage[0];112TempStream << "\nTotal number of mappings created: "113<< GlobalUsage.TotalMappings;114TempStream << "\nMax number of mappings used: "115<< GlobalUsage.MaxUsedMappings << '\n';116117for (unsigned I = 1, E = PRFUsage.size(); I < E; ++I) {118const RegisterFileUsage &RFU = PRFUsage[I];119// Obtain the register file descriptor from the scheduling model.120assert(STI.getSchedModel().hasExtraProcessorInfo() &&121"Unable to find register file info!");122const MCExtraProcessorInfo &PI =123STI.getSchedModel().getExtraProcessorInfo();124assert(I <= PI.NumRegisterFiles && "Unexpected register file index!");125const MCRegisterFileDesc &RFDesc = PI.RegisterFiles[I];126// Skip invalid register files.127if (!RFDesc.NumPhysRegs)128continue;129130TempStream << "\n* Register File #" << I;131TempStream << " -- " << StringRef(RFDesc.Name) << ':';132TempStream << "\n Number of physical registers: ";133if (!RFDesc.NumPhysRegs)134TempStream << "unbounded";135else136TempStream << RFDesc.NumPhysRegs;137TempStream << "\n Total number of mappings created: "138<< RFU.TotalMappings;139TempStream << "\n Max number of mappings used: "140<< RFU.MaxUsedMappings << '\n';141const MoveEliminationInfo &MEI = MoveElimInfo[I];142143if (MEI.TotalMoveEliminationCandidates) {144TempStream << " Number of optimizable moves: "145<< MEI.TotalMoveEliminationCandidates;146double EliminatedMovProportion = (double)MEI.TotalMovesEliminated /147MEI.TotalMoveEliminationCandidates *148100.0;149double ZeroMovProportion = (double)MEI.TotalMovesThatPropagateZero /150MEI.TotalMoveEliminationCandidates * 100.0;151TempStream << "\n Number of moves eliminated: "152<< MEI.TotalMovesEliminated << " "153<< format("(%.1f%%)",154floor((EliminatedMovProportion * 10) + 0.5) / 10);155TempStream << "\n Number of zero moves: "156<< MEI.TotalMovesThatPropagateZero << " "157<< format("(%.1f%%)",158floor((ZeroMovProportion * 10) + 0.5) / 10);159TempStream << "\n Max moves eliminated per cycle: "160<< MEI.MaxMovesEliminatedPerCycle << '\n';161}162}163164TempStream.flush();165OS << Buffer;166}167168} // namespace mca169} // namespace llvm170171172