xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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