xref: /llvm-project/llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp (revision 14f77576c9c4f502267a92992abe3bdcbeb96b2c)
110aa09f0SMatt Davis //===--------------------- RegisterFileStatistics.cpp -----------*- C++ -*-===//
210aa09f0SMatt Davis //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
610aa09f0SMatt Davis //
710aa09f0SMatt Davis //===----------------------------------------------------------------------===//
810aa09f0SMatt Davis /// \file
910aa09f0SMatt Davis ///
1010aa09f0SMatt Davis /// This file implements the RegisterFileStatistics interface.
1110aa09f0SMatt Davis ///
1210aa09f0SMatt Davis //===----------------------------------------------------------------------===//
1310aa09f0SMatt Davis 
1410aa09f0SMatt Davis #include "Views/RegisterFileStatistics.h"
1510aa09f0SMatt Davis #include "llvm/Support/Format.h"
1610aa09f0SMatt Davis 
175a8fd657SFangrui Song namespace llvm {
1810aa09f0SMatt Davis namespace mca {
1910aa09f0SMatt Davis 
RegisterFileStatistics(const MCSubtargetInfo & sti)20db158be6SAndrea Di Biagio RegisterFileStatistics::RegisterFileStatistics(const MCSubtargetInfo &sti)
21b7f120f0SAndrea Di Biagio     : STI(sti) {
2210aa09f0SMatt Davis   const MCSchedModel &SM = STI.getSchedModel();
23fe3bc1b9SAndrea Di Biagio   RegisterFileUsage RFUEmpty = {0, 0, 0};
24fe3bc1b9SAndrea Di Biagio   MoveEliminationInfo MEIEmpty = {0, 0, 0, 0, 0};
2510aa09f0SMatt Davis   if (!SM.hasExtraProcessorInfo()) {
2610aa09f0SMatt Davis     // Assume a single register file.
27fe3bc1b9SAndrea Di Biagio     PRFUsage.emplace_back(RFUEmpty);
28fe3bc1b9SAndrea Di Biagio     MoveElimInfo.emplace_back(MEIEmpty);
2910aa09f0SMatt Davis     return;
3010aa09f0SMatt Davis   }
3110aa09f0SMatt Davis 
3210aa09f0SMatt Davis   // Initialize a RegisterFileUsage for every user defined register file, plus
3310aa09f0SMatt Davis   // the default register file which is always at index #0.
3410aa09f0SMatt Davis   const MCExtraProcessorInfo &PI = SM.getExtraProcessorInfo();
3510aa09f0SMatt Davis   // There is always an "InvalidRegisterFile" entry in tablegen. That entry can
3610aa09f0SMatt Davis   // be skipped. If there are no user defined register files, then reserve a
3710aa09f0SMatt Davis   // single entry for the default register file at index #0.
3810aa09f0SMatt Davis   unsigned NumRegFiles = std::max(PI.NumRegisterFiles, 1U);
39fe3bc1b9SAndrea Di Biagio 
40fe3bc1b9SAndrea Di Biagio   PRFUsage.resize(NumRegFiles);
41fe3bc1b9SAndrea Di Biagio   std::fill(PRFUsage.begin(), PRFUsage.end(), RFUEmpty);
42fe3bc1b9SAndrea Di Biagio 
43fe3bc1b9SAndrea Di Biagio   MoveElimInfo.resize(NumRegFiles);
44fe3bc1b9SAndrea Di Biagio   std::fill(MoveElimInfo.begin(), MoveElimInfo.end(), MEIEmpty);
45fe3bc1b9SAndrea Di Biagio }
46fe3bc1b9SAndrea Di Biagio 
updateRegisterFileUsage(ArrayRef<unsigned> UsedPhysRegs)47fe3bc1b9SAndrea Di Biagio void RegisterFileStatistics::updateRegisterFileUsage(
48fe3bc1b9SAndrea Di Biagio     ArrayRef<unsigned> UsedPhysRegs) {
49fe3bc1b9SAndrea Di Biagio   for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I) {
50fe3bc1b9SAndrea Di Biagio     RegisterFileUsage &RFU = PRFUsage[I];
51fe3bc1b9SAndrea Di Biagio     unsigned NumUsedPhysRegs = UsedPhysRegs[I];
52fe3bc1b9SAndrea Di Biagio     RFU.CurrentlyUsedMappings += NumUsedPhysRegs;
53fe3bc1b9SAndrea Di Biagio     RFU.TotalMappings += NumUsedPhysRegs;
54fe3bc1b9SAndrea Di Biagio     RFU.MaxUsedMappings =
55fe3bc1b9SAndrea Di Biagio         std::max(RFU.MaxUsedMappings, RFU.CurrentlyUsedMappings);
56fe3bc1b9SAndrea Di Biagio   }
57fe3bc1b9SAndrea Di Biagio }
58fe3bc1b9SAndrea Di Biagio 
updateMoveElimInfo(const Instruction & Inst)59fe3bc1b9SAndrea Di Biagio void RegisterFileStatistics::updateMoveElimInfo(const Instruction &Inst) {
60fe3bc1b9SAndrea Di Biagio   if (!Inst.isOptimizableMove())
61fe3bc1b9SAndrea Di Biagio     return;
62fe3bc1b9SAndrea Di Biagio 
63*de1843e5SAndrea Di Biagio   if (Inst.getDefs().size() != Inst.getUses().size())
64*de1843e5SAndrea Di Biagio     return;
65*de1843e5SAndrea Di Biagio 
66*de1843e5SAndrea Di Biagio   for (size_t I = 0, E = Inst.getDefs().size(); I < E; ++I) {
67*de1843e5SAndrea Di Biagio     const WriteState &WS = Inst.getDefs()[I];
68*de1843e5SAndrea Di Biagio     const ReadState &RS = Inst.getUses()[E - (I + 1)];
69fe3bc1b9SAndrea Di Biagio 
70fe3bc1b9SAndrea Di Biagio     MoveEliminationInfo &Info =
71fe3bc1b9SAndrea Di Biagio         MoveElimInfo[Inst.getDefs()[0].getRegisterFileID()];
72fe3bc1b9SAndrea Di Biagio     Info.TotalMoveEliminationCandidates++;
73fe3bc1b9SAndrea Di Biagio     if (WS.isEliminated())
74fe3bc1b9SAndrea Di Biagio       Info.CurrentMovesEliminated++;
75fe3bc1b9SAndrea Di Biagio     if (WS.isWriteZero() && RS.isReadZero())
76fe3bc1b9SAndrea Di Biagio       Info.TotalMovesThatPropagateZero++;
7710aa09f0SMatt Davis   }
78*de1843e5SAndrea Di Biagio }
7910aa09f0SMatt Davis 
onEvent(const HWInstructionEvent & Event)8010aa09f0SMatt Davis void RegisterFileStatistics::onEvent(const HWInstructionEvent &Event) {
8110aa09f0SMatt Davis   switch (Event.Type) {
8210aa09f0SMatt Davis   default:
8310aa09f0SMatt Davis     break;
8410aa09f0SMatt Davis   case HWInstructionEvent::Retired: {
8510aa09f0SMatt Davis     const auto &RE = static_cast<const HWInstructionRetiredEvent &>(Event);
86fe3bc1b9SAndrea Di Biagio     for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I)
87fe3bc1b9SAndrea Di Biagio       PRFUsage[I].CurrentlyUsedMappings -= RE.FreedPhysRegs[I];
8810aa09f0SMatt Davis     break;
8910aa09f0SMatt Davis   }
9010aa09f0SMatt Davis   case HWInstructionEvent::Dispatched: {
9110aa09f0SMatt Davis     const auto &DE = static_cast<const HWInstructionDispatchedEvent &>(Event);
92fe3bc1b9SAndrea Di Biagio     updateRegisterFileUsage(DE.UsedPhysRegs);
93fe3bc1b9SAndrea Di Biagio     updateMoveElimInfo(*DE.IR.getInstruction());
9410aa09f0SMatt Davis   }
9510aa09f0SMatt Davis   }
9610aa09f0SMatt Davis }
97fe3bc1b9SAndrea Di Biagio 
onCycleEnd()98fe3bc1b9SAndrea Di Biagio void RegisterFileStatistics::onCycleEnd() {
99fe3bc1b9SAndrea Di Biagio   for (MoveEliminationInfo &MEI : MoveElimInfo) {
100fe3bc1b9SAndrea Di Biagio     unsigned &CurrentMax = MEI.MaxMovesEliminatedPerCycle;
101fe3bc1b9SAndrea Di Biagio     CurrentMax = std::max(CurrentMax, MEI.CurrentMovesEliminated);
102fe3bc1b9SAndrea Di Biagio     MEI.TotalMovesEliminated += MEI.CurrentMovesEliminated;
103fe3bc1b9SAndrea Di Biagio     MEI.CurrentMovesEliminated = 0;
104fe3bc1b9SAndrea Di Biagio   }
10510aa09f0SMatt Davis }
10610aa09f0SMatt Davis 
printView(raw_ostream & OS) const10710aa09f0SMatt Davis void RegisterFileStatistics::printView(raw_ostream &OS) const {
10810aa09f0SMatt Davis   std::string Buffer;
10910aa09f0SMatt Davis   raw_string_ostream TempStream(Buffer);
11010aa09f0SMatt Davis 
11110aa09f0SMatt Davis   TempStream << "\n\nRegister File statistics:";
112fe3bc1b9SAndrea Di Biagio   const RegisterFileUsage &GlobalUsage = PRFUsage[0];
11310aa09f0SMatt Davis   TempStream << "\nTotal number of mappings created:    "
11410aa09f0SMatt Davis              << GlobalUsage.TotalMappings;
11510aa09f0SMatt Davis   TempStream << "\nMax number of mappings used:         "
11610aa09f0SMatt Davis              << GlobalUsage.MaxUsedMappings << '\n';
11710aa09f0SMatt Davis 
118fe3bc1b9SAndrea Di Biagio   for (unsigned I = 1, E = PRFUsage.size(); I < E; ++I) {
119fe3bc1b9SAndrea Di Biagio     const RegisterFileUsage &RFU = PRFUsage[I];
12010aa09f0SMatt Davis     // Obtain the register file descriptor from the scheduling model.
12110aa09f0SMatt Davis     assert(STI.getSchedModel().hasExtraProcessorInfo() &&
12210aa09f0SMatt Davis            "Unable to find register file info!");
12310aa09f0SMatt Davis     const MCExtraProcessorInfo &PI =
12410aa09f0SMatt Davis         STI.getSchedModel().getExtraProcessorInfo();
12510aa09f0SMatt Davis     assert(I <= PI.NumRegisterFiles && "Unexpected register file index!");
12610aa09f0SMatt Davis     const MCRegisterFileDesc &RFDesc = PI.RegisterFiles[I];
12710aa09f0SMatt Davis     // Skip invalid register files.
12810aa09f0SMatt Davis     if (!RFDesc.NumPhysRegs)
12910aa09f0SMatt Davis       continue;
13010aa09f0SMatt Davis 
13110aa09f0SMatt Davis     TempStream << "\n*  Register File #" << I;
13210aa09f0SMatt Davis     TempStream << " -- " << StringRef(RFDesc.Name) << ':';
13310aa09f0SMatt Davis     TempStream << "\n   Number of physical registers:     ";
13410aa09f0SMatt Davis     if (!RFDesc.NumPhysRegs)
13510aa09f0SMatt Davis       TempStream << "unbounded";
13610aa09f0SMatt Davis     else
13710aa09f0SMatt Davis       TempStream << RFDesc.NumPhysRegs;
13810aa09f0SMatt Davis     TempStream << "\n   Total number of mappings created: "
13910aa09f0SMatt Davis                << RFU.TotalMappings;
14010aa09f0SMatt Davis     TempStream << "\n   Max number of mappings used:      "
14110aa09f0SMatt Davis                << RFU.MaxUsedMappings << '\n';
142fe3bc1b9SAndrea Di Biagio     const MoveEliminationInfo &MEI = MoveElimInfo[I];
143fe3bc1b9SAndrea Di Biagio 
144fe3bc1b9SAndrea Di Biagio     if (MEI.TotalMoveEliminationCandidates) {
145fe3bc1b9SAndrea Di Biagio       TempStream << "   Number of optimizable moves:      "
146fe3bc1b9SAndrea Di Biagio                  << MEI.TotalMoveEliminationCandidates;
147fe3bc1b9SAndrea Di Biagio       double EliminatedMovProportion = (double)MEI.TotalMovesEliminated /
148fe3bc1b9SAndrea Di Biagio                                        MEI.TotalMoveEliminationCandidates *
149fe3bc1b9SAndrea Di Biagio                                        100.0;
150fe3bc1b9SAndrea Di Biagio       double ZeroMovProportion = (double)MEI.TotalMovesThatPropagateZero /
151fe3bc1b9SAndrea Di Biagio                                  MEI.TotalMoveEliminationCandidates * 100.0;
152fe3bc1b9SAndrea Di Biagio       TempStream << "\n   Number of moves eliminated:       "
153fe3bc1b9SAndrea Di Biagio                  << MEI.TotalMovesEliminated << "  "
154fe3bc1b9SAndrea Di Biagio                  << format("(%.1f%%)",
155fe3bc1b9SAndrea Di Biagio                            floor((EliminatedMovProportion * 10) + 0.5) / 10);
156fe3bc1b9SAndrea Di Biagio       TempStream << "\n   Number of zero moves:             "
157fe3bc1b9SAndrea Di Biagio                  << MEI.TotalMovesThatPropagateZero << "  "
158fe3bc1b9SAndrea Di Biagio                  << format("(%.1f%%)",
159fe3bc1b9SAndrea Di Biagio                            floor((ZeroMovProportion * 10) + 0.5) / 10);
160fe3bc1b9SAndrea Di Biagio       TempStream << "\n   Max moves eliminated per cycle:   "
161fe3bc1b9SAndrea Di Biagio                  << MEI.MaxMovesEliminatedPerCycle << '\n';
162fe3bc1b9SAndrea Di Biagio     }
16310aa09f0SMatt Davis   }
16410aa09f0SMatt Davis 
16510aa09f0SMatt Davis   TempStream.flush();
16610aa09f0SMatt Davis   OS << Buffer;
16710aa09f0SMatt Davis }
16810aa09f0SMatt Davis 
16910aa09f0SMatt Davis } // namespace mca
1705a8fd657SFangrui Song } // namespace llvm
171