10b57cec5SDimitry Andric //===--------------------- RegisterFileStatistics.cpp -----------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric ///
100b57cec5SDimitry Andric /// This file implements the RegisterFileStatistics interface.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "Views/RegisterFileStatistics.h"
150b57cec5SDimitry Andric #include "llvm/Support/Format.h"
160b57cec5SDimitry Andric
170b57cec5SDimitry Andric namespace llvm {
180b57cec5SDimitry Andric namespace mca {
190b57cec5SDimitry Andric
RegisterFileStatistics(const MCSubtargetInfo & sti)200b57cec5SDimitry Andric RegisterFileStatistics::RegisterFileStatistics(const MCSubtargetInfo &sti)
210b57cec5SDimitry Andric : STI(sti) {
220b57cec5SDimitry Andric const MCSchedModel &SM = STI.getSchedModel();
230b57cec5SDimitry Andric RegisterFileUsage RFUEmpty = {0, 0, 0};
240b57cec5SDimitry Andric MoveEliminationInfo MEIEmpty = {0, 0, 0, 0, 0};
250b57cec5SDimitry Andric if (!SM.hasExtraProcessorInfo()) {
260b57cec5SDimitry Andric // Assume a single register file.
270b57cec5SDimitry Andric PRFUsage.emplace_back(RFUEmpty);
280b57cec5SDimitry Andric MoveElimInfo.emplace_back(MEIEmpty);
290b57cec5SDimitry Andric return;
300b57cec5SDimitry Andric }
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric // Initialize a RegisterFileUsage for every user defined register file, plus
330b57cec5SDimitry Andric // the default register file which is always at index #0.
340b57cec5SDimitry Andric const MCExtraProcessorInfo &PI = SM.getExtraProcessorInfo();
350b57cec5SDimitry Andric // There is always an "InvalidRegisterFile" entry in tablegen. That entry can
360b57cec5SDimitry Andric // be skipped. If there are no user defined register files, then reserve a
370b57cec5SDimitry Andric // single entry for the default register file at index #0.
380b57cec5SDimitry Andric unsigned NumRegFiles = std::max(PI.NumRegisterFiles, 1U);
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric PRFUsage.resize(NumRegFiles);
410b57cec5SDimitry Andric std::fill(PRFUsage.begin(), PRFUsage.end(), RFUEmpty);
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric MoveElimInfo.resize(NumRegFiles);
440b57cec5SDimitry Andric std::fill(MoveElimInfo.begin(), MoveElimInfo.end(), MEIEmpty);
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric
updateRegisterFileUsage(ArrayRef<unsigned> UsedPhysRegs)470b57cec5SDimitry Andric void RegisterFileStatistics::updateRegisterFileUsage(
480b57cec5SDimitry Andric ArrayRef<unsigned> UsedPhysRegs) {
490b57cec5SDimitry Andric for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I) {
500b57cec5SDimitry Andric RegisterFileUsage &RFU = PRFUsage[I];
510b57cec5SDimitry Andric unsigned NumUsedPhysRegs = UsedPhysRegs[I];
520b57cec5SDimitry Andric RFU.CurrentlyUsedMappings += NumUsedPhysRegs;
530b57cec5SDimitry Andric RFU.TotalMappings += NumUsedPhysRegs;
540b57cec5SDimitry Andric RFU.MaxUsedMappings =
550b57cec5SDimitry Andric std::max(RFU.MaxUsedMappings, RFU.CurrentlyUsedMappings);
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric
updateMoveElimInfo(const Instruction & Inst)590b57cec5SDimitry Andric void RegisterFileStatistics::updateMoveElimInfo(const Instruction &Inst) {
600b57cec5SDimitry Andric if (!Inst.isOptimizableMove())
610b57cec5SDimitry Andric return;
620b57cec5SDimitry Andric
63*fe6060f1SDimitry Andric if (Inst.getDefs().size() != Inst.getUses().size())
64*fe6060f1SDimitry Andric return;
65*fe6060f1SDimitry Andric
66*fe6060f1SDimitry Andric for (size_t I = 0, E = Inst.getDefs().size(); I < E; ++I) {
67*fe6060f1SDimitry Andric const WriteState &WS = Inst.getDefs()[I];
68*fe6060f1SDimitry Andric const ReadState &RS = Inst.getUses()[E - (I + 1)];
690b57cec5SDimitry Andric
700b57cec5SDimitry Andric MoveEliminationInfo &Info =
710b57cec5SDimitry Andric MoveElimInfo[Inst.getDefs()[0].getRegisterFileID()];
720b57cec5SDimitry Andric Info.TotalMoveEliminationCandidates++;
730b57cec5SDimitry Andric if (WS.isEliminated())
740b57cec5SDimitry Andric Info.CurrentMovesEliminated++;
750b57cec5SDimitry Andric if (WS.isWriteZero() && RS.isReadZero())
760b57cec5SDimitry Andric Info.TotalMovesThatPropagateZero++;
770b57cec5SDimitry Andric }
78*fe6060f1SDimitry Andric }
790b57cec5SDimitry Andric
onEvent(const HWInstructionEvent & Event)800b57cec5SDimitry Andric void RegisterFileStatistics::onEvent(const HWInstructionEvent &Event) {
810b57cec5SDimitry Andric switch (Event.Type) {
820b57cec5SDimitry Andric default:
830b57cec5SDimitry Andric break;
840b57cec5SDimitry Andric case HWInstructionEvent::Retired: {
850b57cec5SDimitry Andric const auto &RE = static_cast<const HWInstructionRetiredEvent &>(Event);
860b57cec5SDimitry Andric for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I)
870b57cec5SDimitry Andric PRFUsage[I].CurrentlyUsedMappings -= RE.FreedPhysRegs[I];
880b57cec5SDimitry Andric break;
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric case HWInstructionEvent::Dispatched: {
910b57cec5SDimitry Andric const auto &DE = static_cast<const HWInstructionDispatchedEvent &>(Event);
920b57cec5SDimitry Andric updateRegisterFileUsage(DE.UsedPhysRegs);
930b57cec5SDimitry Andric updateMoveElimInfo(*DE.IR.getInstruction());
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric
onCycleEnd()980b57cec5SDimitry Andric void RegisterFileStatistics::onCycleEnd() {
990b57cec5SDimitry Andric for (MoveEliminationInfo &MEI : MoveElimInfo) {
1000b57cec5SDimitry Andric unsigned &CurrentMax = MEI.MaxMovesEliminatedPerCycle;
1010b57cec5SDimitry Andric CurrentMax = std::max(CurrentMax, MEI.CurrentMovesEliminated);
1020b57cec5SDimitry Andric MEI.TotalMovesEliminated += MEI.CurrentMovesEliminated;
1030b57cec5SDimitry Andric MEI.CurrentMovesEliminated = 0;
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric
printView(raw_ostream & OS) const1070b57cec5SDimitry Andric void RegisterFileStatistics::printView(raw_ostream &OS) const {
1080b57cec5SDimitry Andric std::string Buffer;
1090b57cec5SDimitry Andric raw_string_ostream TempStream(Buffer);
1100b57cec5SDimitry Andric
1110b57cec5SDimitry Andric TempStream << "\n\nRegister File statistics:";
1120b57cec5SDimitry Andric const RegisterFileUsage &GlobalUsage = PRFUsage[0];
1130b57cec5SDimitry Andric TempStream << "\nTotal number of mappings created: "
1140b57cec5SDimitry Andric << GlobalUsage.TotalMappings;
1150b57cec5SDimitry Andric TempStream << "\nMax number of mappings used: "
1160b57cec5SDimitry Andric << GlobalUsage.MaxUsedMappings << '\n';
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andric for (unsigned I = 1, E = PRFUsage.size(); I < E; ++I) {
1190b57cec5SDimitry Andric const RegisterFileUsage &RFU = PRFUsage[I];
1200b57cec5SDimitry Andric // Obtain the register file descriptor from the scheduling model.
1210b57cec5SDimitry Andric assert(STI.getSchedModel().hasExtraProcessorInfo() &&
1220b57cec5SDimitry Andric "Unable to find register file info!");
1230b57cec5SDimitry Andric const MCExtraProcessorInfo &PI =
1240b57cec5SDimitry Andric STI.getSchedModel().getExtraProcessorInfo();
1250b57cec5SDimitry Andric assert(I <= PI.NumRegisterFiles && "Unexpected register file index!");
1260b57cec5SDimitry Andric const MCRegisterFileDesc &RFDesc = PI.RegisterFiles[I];
1270b57cec5SDimitry Andric // Skip invalid register files.
1280b57cec5SDimitry Andric if (!RFDesc.NumPhysRegs)
1290b57cec5SDimitry Andric continue;
1300b57cec5SDimitry Andric
1310b57cec5SDimitry Andric TempStream << "\n* Register File #" << I;
1320b57cec5SDimitry Andric TempStream << " -- " << StringRef(RFDesc.Name) << ':';
1330b57cec5SDimitry Andric TempStream << "\n Number of physical registers: ";
1340b57cec5SDimitry Andric if (!RFDesc.NumPhysRegs)
1350b57cec5SDimitry Andric TempStream << "unbounded";
1360b57cec5SDimitry Andric else
1370b57cec5SDimitry Andric TempStream << RFDesc.NumPhysRegs;
1380b57cec5SDimitry Andric TempStream << "\n Total number of mappings created: "
1390b57cec5SDimitry Andric << RFU.TotalMappings;
1400b57cec5SDimitry Andric TempStream << "\n Max number of mappings used: "
1410b57cec5SDimitry Andric << RFU.MaxUsedMappings << '\n';
1420b57cec5SDimitry Andric const MoveEliminationInfo &MEI = MoveElimInfo[I];
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric if (MEI.TotalMoveEliminationCandidates) {
1450b57cec5SDimitry Andric TempStream << " Number of optimizable moves: "
1460b57cec5SDimitry Andric << MEI.TotalMoveEliminationCandidates;
1470b57cec5SDimitry Andric double EliminatedMovProportion = (double)MEI.TotalMovesEliminated /
1480b57cec5SDimitry Andric MEI.TotalMoveEliminationCandidates *
1490b57cec5SDimitry Andric 100.0;
1500b57cec5SDimitry Andric double ZeroMovProportion = (double)MEI.TotalMovesThatPropagateZero /
1510b57cec5SDimitry Andric MEI.TotalMoveEliminationCandidates * 100.0;
1520b57cec5SDimitry Andric TempStream << "\n Number of moves eliminated: "
1530b57cec5SDimitry Andric << MEI.TotalMovesEliminated << " "
1540b57cec5SDimitry Andric << format("(%.1f%%)",
1550b57cec5SDimitry Andric floor((EliminatedMovProportion * 10) + 0.5) / 10);
1560b57cec5SDimitry Andric TempStream << "\n Number of zero moves: "
1570b57cec5SDimitry Andric << MEI.TotalMovesThatPropagateZero << " "
1580b57cec5SDimitry Andric << format("(%.1f%%)",
1590b57cec5SDimitry Andric floor((ZeroMovProportion * 10) + 0.5) / 10);
1600b57cec5SDimitry Andric TempStream << "\n Max moves eliminated per cycle: "
1610b57cec5SDimitry Andric << MEI.MaxMovesEliminatedPerCycle << '\n';
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andric TempStream.flush();
1660b57cec5SDimitry Andric OS << Buffer;
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric } // namespace mca
1700b57cec5SDimitry Andric } // namespace llvm
171