xref: /openbsd-src/gnu/llvm/llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp (revision 73471bf04ceb096474c7f0fa83b1b65c70a787a1)
109467b48Spatrick //===--------------------- RegisterFileStatistics.cpp -----------*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick /// \file
909467b48Spatrick ///
1009467b48Spatrick /// This file implements the RegisterFileStatistics interface.
1109467b48Spatrick ///
1209467b48Spatrick //===----------------------------------------------------------------------===//
1309467b48Spatrick 
1409467b48Spatrick #include "Views/RegisterFileStatistics.h"
1509467b48Spatrick #include "llvm/Support/Format.h"
1609467b48Spatrick 
1709467b48Spatrick namespace llvm {
1809467b48Spatrick namespace mca {
1909467b48Spatrick 
RegisterFileStatistics(const MCSubtargetInfo & sti)2009467b48Spatrick RegisterFileStatistics::RegisterFileStatistics(const MCSubtargetInfo &sti)
2109467b48Spatrick     : STI(sti) {
2209467b48Spatrick   const MCSchedModel &SM = STI.getSchedModel();
2309467b48Spatrick   RegisterFileUsage RFUEmpty = {0, 0, 0};
2409467b48Spatrick   MoveEliminationInfo MEIEmpty = {0, 0, 0, 0, 0};
2509467b48Spatrick   if (!SM.hasExtraProcessorInfo()) {
2609467b48Spatrick     // Assume a single register file.
2709467b48Spatrick     PRFUsage.emplace_back(RFUEmpty);
2809467b48Spatrick     MoveElimInfo.emplace_back(MEIEmpty);
2909467b48Spatrick     return;
3009467b48Spatrick   }
3109467b48Spatrick 
3209467b48Spatrick   // Initialize a RegisterFileUsage for every user defined register file, plus
3309467b48Spatrick   // the default register file which is always at index #0.
3409467b48Spatrick   const MCExtraProcessorInfo &PI = SM.getExtraProcessorInfo();
3509467b48Spatrick   // There is always an "InvalidRegisterFile" entry in tablegen. That entry can
3609467b48Spatrick   // be skipped. If there are no user defined register files, then reserve a
3709467b48Spatrick   // single entry for the default register file at index #0.
3809467b48Spatrick   unsigned NumRegFiles = std::max(PI.NumRegisterFiles, 1U);
3909467b48Spatrick 
4009467b48Spatrick   PRFUsage.resize(NumRegFiles);
4109467b48Spatrick   std::fill(PRFUsage.begin(), PRFUsage.end(), RFUEmpty);
4209467b48Spatrick 
4309467b48Spatrick   MoveElimInfo.resize(NumRegFiles);
4409467b48Spatrick   std::fill(MoveElimInfo.begin(), MoveElimInfo.end(), MEIEmpty);
4509467b48Spatrick }
4609467b48Spatrick 
updateRegisterFileUsage(ArrayRef<unsigned> UsedPhysRegs)4709467b48Spatrick void RegisterFileStatistics::updateRegisterFileUsage(
4809467b48Spatrick     ArrayRef<unsigned> UsedPhysRegs) {
4909467b48Spatrick   for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I) {
5009467b48Spatrick     RegisterFileUsage &RFU = PRFUsage[I];
5109467b48Spatrick     unsigned NumUsedPhysRegs = UsedPhysRegs[I];
5209467b48Spatrick     RFU.CurrentlyUsedMappings += NumUsedPhysRegs;
5309467b48Spatrick     RFU.TotalMappings += NumUsedPhysRegs;
5409467b48Spatrick     RFU.MaxUsedMappings =
5509467b48Spatrick         std::max(RFU.MaxUsedMappings, RFU.CurrentlyUsedMappings);
5609467b48Spatrick   }
5709467b48Spatrick }
5809467b48Spatrick 
updateMoveElimInfo(const Instruction & Inst)5909467b48Spatrick void RegisterFileStatistics::updateMoveElimInfo(const Instruction &Inst) {
6009467b48Spatrick   if (!Inst.isOptimizableMove())
6109467b48Spatrick     return;
6209467b48Spatrick 
63*73471bf0Spatrick   if (Inst.getDefs().size() != Inst.getUses().size())
64*73471bf0Spatrick     return;
65*73471bf0Spatrick 
66*73471bf0Spatrick   for (size_t I = 0, E = Inst.getDefs().size(); I < E; ++I) {
67*73471bf0Spatrick     const WriteState &WS = Inst.getDefs()[I];
68*73471bf0Spatrick     const ReadState &RS = Inst.getUses()[E - (I + 1)];
6909467b48Spatrick 
7009467b48Spatrick     MoveEliminationInfo &Info =
7109467b48Spatrick         MoveElimInfo[Inst.getDefs()[0].getRegisterFileID()];
7209467b48Spatrick     Info.TotalMoveEliminationCandidates++;
7309467b48Spatrick     if (WS.isEliminated())
7409467b48Spatrick       Info.CurrentMovesEliminated++;
7509467b48Spatrick     if (WS.isWriteZero() && RS.isReadZero())
7609467b48Spatrick       Info.TotalMovesThatPropagateZero++;
7709467b48Spatrick   }
78*73471bf0Spatrick }
7909467b48Spatrick 
onEvent(const HWInstructionEvent & Event)8009467b48Spatrick void RegisterFileStatistics::onEvent(const HWInstructionEvent &Event) {
8109467b48Spatrick   switch (Event.Type) {
8209467b48Spatrick   default:
8309467b48Spatrick     break;
8409467b48Spatrick   case HWInstructionEvent::Retired: {
8509467b48Spatrick     const auto &RE = static_cast<const HWInstructionRetiredEvent &>(Event);
8609467b48Spatrick     for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I)
8709467b48Spatrick       PRFUsage[I].CurrentlyUsedMappings -= RE.FreedPhysRegs[I];
8809467b48Spatrick     break;
8909467b48Spatrick   }
9009467b48Spatrick   case HWInstructionEvent::Dispatched: {
9109467b48Spatrick     const auto &DE = static_cast<const HWInstructionDispatchedEvent &>(Event);
9209467b48Spatrick     updateRegisterFileUsage(DE.UsedPhysRegs);
9309467b48Spatrick     updateMoveElimInfo(*DE.IR.getInstruction());
9409467b48Spatrick   }
9509467b48Spatrick   }
9609467b48Spatrick }
9709467b48Spatrick 
onCycleEnd()9809467b48Spatrick void RegisterFileStatistics::onCycleEnd() {
9909467b48Spatrick   for (MoveEliminationInfo &MEI : MoveElimInfo) {
10009467b48Spatrick     unsigned &CurrentMax = MEI.MaxMovesEliminatedPerCycle;
10109467b48Spatrick     CurrentMax = std::max(CurrentMax, MEI.CurrentMovesEliminated);
10209467b48Spatrick     MEI.TotalMovesEliminated += MEI.CurrentMovesEliminated;
10309467b48Spatrick     MEI.CurrentMovesEliminated = 0;
10409467b48Spatrick   }
10509467b48Spatrick }
10609467b48Spatrick 
printView(raw_ostream & OS) const10709467b48Spatrick void RegisterFileStatistics::printView(raw_ostream &OS) const {
10809467b48Spatrick   std::string Buffer;
10909467b48Spatrick   raw_string_ostream TempStream(Buffer);
11009467b48Spatrick 
11109467b48Spatrick   TempStream << "\n\nRegister File statistics:";
11209467b48Spatrick   const RegisterFileUsage &GlobalUsage = PRFUsage[0];
11309467b48Spatrick   TempStream << "\nTotal number of mappings created:    "
11409467b48Spatrick              << GlobalUsage.TotalMappings;
11509467b48Spatrick   TempStream << "\nMax number of mappings used:         "
11609467b48Spatrick              << GlobalUsage.MaxUsedMappings << '\n';
11709467b48Spatrick 
11809467b48Spatrick   for (unsigned I = 1, E = PRFUsage.size(); I < E; ++I) {
11909467b48Spatrick     const RegisterFileUsage &RFU = PRFUsage[I];
12009467b48Spatrick     // Obtain the register file descriptor from the scheduling model.
12109467b48Spatrick     assert(STI.getSchedModel().hasExtraProcessorInfo() &&
12209467b48Spatrick            "Unable to find register file info!");
12309467b48Spatrick     const MCExtraProcessorInfo &PI =
12409467b48Spatrick         STI.getSchedModel().getExtraProcessorInfo();
12509467b48Spatrick     assert(I <= PI.NumRegisterFiles && "Unexpected register file index!");
12609467b48Spatrick     const MCRegisterFileDesc &RFDesc = PI.RegisterFiles[I];
12709467b48Spatrick     // Skip invalid register files.
12809467b48Spatrick     if (!RFDesc.NumPhysRegs)
12909467b48Spatrick       continue;
13009467b48Spatrick 
13109467b48Spatrick     TempStream << "\n*  Register File #" << I;
13209467b48Spatrick     TempStream << " -- " << StringRef(RFDesc.Name) << ':';
13309467b48Spatrick     TempStream << "\n   Number of physical registers:     ";
13409467b48Spatrick     if (!RFDesc.NumPhysRegs)
13509467b48Spatrick       TempStream << "unbounded";
13609467b48Spatrick     else
13709467b48Spatrick       TempStream << RFDesc.NumPhysRegs;
13809467b48Spatrick     TempStream << "\n   Total number of mappings created: "
13909467b48Spatrick                << RFU.TotalMappings;
14009467b48Spatrick     TempStream << "\n   Max number of mappings used:      "
14109467b48Spatrick                << RFU.MaxUsedMappings << '\n';
14209467b48Spatrick     const MoveEliminationInfo &MEI = MoveElimInfo[I];
14309467b48Spatrick 
14409467b48Spatrick     if (MEI.TotalMoveEliminationCandidates) {
14509467b48Spatrick       TempStream << "   Number of optimizable moves:      "
14609467b48Spatrick                  << MEI.TotalMoveEliminationCandidates;
14709467b48Spatrick       double EliminatedMovProportion = (double)MEI.TotalMovesEliminated /
14809467b48Spatrick                                        MEI.TotalMoveEliminationCandidates *
14909467b48Spatrick                                        100.0;
15009467b48Spatrick       double ZeroMovProportion = (double)MEI.TotalMovesThatPropagateZero /
15109467b48Spatrick                                  MEI.TotalMoveEliminationCandidates * 100.0;
15209467b48Spatrick       TempStream << "\n   Number of moves eliminated:       "
15309467b48Spatrick                  << MEI.TotalMovesEliminated << "  "
15409467b48Spatrick                  << format("(%.1f%%)",
15509467b48Spatrick                            floor((EliminatedMovProportion * 10) + 0.5) / 10);
15609467b48Spatrick       TempStream << "\n   Number of zero moves:             "
15709467b48Spatrick                  << MEI.TotalMovesThatPropagateZero << "  "
15809467b48Spatrick                  << format("(%.1f%%)",
15909467b48Spatrick                            floor((ZeroMovProportion * 10) + 0.5) / 10);
16009467b48Spatrick       TempStream << "\n   Max moves eliminated per cycle:   "
16109467b48Spatrick                  << MEI.MaxMovesEliminatedPerCycle << '\n';
16209467b48Spatrick     }
16309467b48Spatrick   }
16409467b48Spatrick 
16509467b48Spatrick   TempStream.flush();
16609467b48Spatrick   OS << Buffer;
16709467b48Spatrick }
16809467b48Spatrick 
16909467b48Spatrick } // namespace mca
17009467b48Spatrick } // namespace llvm
171