]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / llvm-mca / Views / RegisterFileStatistics.cpp
1 //===--------------------- RegisterFileStatistics.cpp -----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 ///
10 /// This file implements the RegisterFileStatistics interface.
11 ///
12 //===----------------------------------------------------------------------===//
13
14 #include "Views/RegisterFileStatistics.h"
15 #include "llvm/Support/Format.h"
16
17 namespace llvm {
18 namespace mca {
19
20 RegisterFileStatistics::RegisterFileStatistics(const MCSubtargetInfo &sti)
21     : STI(sti) {
22   const MCSchedModel &SM = STI.getSchedModel();
23   RegisterFileUsage RFUEmpty = {0, 0, 0};
24   MoveEliminationInfo MEIEmpty = {0, 0, 0, 0, 0};
25   if (!SM.hasExtraProcessorInfo()) {
26     // Assume a single register file.
27     PRFUsage.emplace_back(RFUEmpty);
28     MoveElimInfo.emplace_back(MEIEmpty);
29     return;
30   }
31
32   // Initialize a RegisterFileUsage for every user defined register file, plus
33   // the default register file which is always at index #0.
34   const MCExtraProcessorInfo &PI = SM.getExtraProcessorInfo();
35   // There is always an "InvalidRegisterFile" entry in tablegen. That entry can
36   // be skipped. If there are no user defined register files, then reserve a
37   // single entry for the default register file at index #0.
38   unsigned NumRegFiles = std::max(PI.NumRegisterFiles, 1U);
39
40   PRFUsage.resize(NumRegFiles);
41   std::fill(PRFUsage.begin(), PRFUsage.end(), RFUEmpty);
42
43   MoveElimInfo.resize(NumRegFiles);
44   std::fill(MoveElimInfo.begin(), MoveElimInfo.end(), MEIEmpty);
45 }
46
47 void RegisterFileStatistics::updateRegisterFileUsage(
48     ArrayRef<unsigned> UsedPhysRegs) {
49   for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I) {
50     RegisterFileUsage &RFU = PRFUsage[I];
51     unsigned NumUsedPhysRegs = UsedPhysRegs[I];
52     RFU.CurrentlyUsedMappings += NumUsedPhysRegs;
53     RFU.TotalMappings += NumUsedPhysRegs;
54     RFU.MaxUsedMappings =
55         std::max(RFU.MaxUsedMappings, RFU.CurrentlyUsedMappings);
56   }
57 }
58
59 void RegisterFileStatistics::updateMoveElimInfo(const Instruction &Inst) {
60   if (!Inst.isOptimizableMove())
61     return;
62
63   assert(Inst.getDefs().size() == 1 && "Expected a single definition!");
64   assert(Inst.getUses().size() == 1 && "Expected a single register use!");
65   const WriteState &WS = Inst.getDefs()[0];
66   const ReadState &RS = Inst.getUses()[0];
67
68   MoveEliminationInfo &Info =
69       MoveElimInfo[Inst.getDefs()[0].getRegisterFileID()];
70   Info.TotalMoveEliminationCandidates++;
71   if (WS.isEliminated())
72     Info.CurrentMovesEliminated++;
73   if (WS.isWriteZero() && RS.isReadZero())
74     Info.TotalMovesThatPropagateZero++;
75 }
76
77 void RegisterFileStatistics::onEvent(const HWInstructionEvent &Event) {
78   switch (Event.Type) {
79   default:
80     break;
81   case HWInstructionEvent::Retired: {
82     const auto &RE = static_cast<const HWInstructionRetiredEvent &>(Event);
83     for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I)
84       PRFUsage[I].CurrentlyUsedMappings -= RE.FreedPhysRegs[I];
85     break;
86   }
87   case HWInstructionEvent::Dispatched: {
88     const auto &DE = static_cast<const HWInstructionDispatchedEvent &>(Event);
89     updateRegisterFileUsage(DE.UsedPhysRegs);
90     updateMoveElimInfo(*DE.IR.getInstruction());
91   }
92   }
93 }
94
95 void RegisterFileStatistics::onCycleEnd() {
96   for (MoveEliminationInfo &MEI : MoveElimInfo) {
97     unsigned &CurrentMax = MEI.MaxMovesEliminatedPerCycle;
98     CurrentMax = std::max(CurrentMax, MEI.CurrentMovesEliminated);
99     MEI.TotalMovesEliminated += MEI.CurrentMovesEliminated;
100     MEI.CurrentMovesEliminated = 0;
101   }
102 }
103
104 void RegisterFileStatistics::printView(raw_ostream &OS) const {
105   std::string Buffer;
106   raw_string_ostream TempStream(Buffer);
107
108   TempStream << "\n\nRegister File statistics:";
109   const RegisterFileUsage &GlobalUsage = PRFUsage[0];
110   TempStream << "\nTotal number of mappings created:    "
111              << GlobalUsage.TotalMappings;
112   TempStream << "\nMax number of mappings used:         "
113              << GlobalUsage.MaxUsedMappings << '\n';
114
115   for (unsigned I = 1, E = PRFUsage.size(); I < E; ++I) {
116     const RegisterFileUsage &RFU = PRFUsage[I];
117     // Obtain the register file descriptor from the scheduling model.
118     assert(STI.getSchedModel().hasExtraProcessorInfo() &&
119            "Unable to find register file info!");
120     const MCExtraProcessorInfo &PI =
121         STI.getSchedModel().getExtraProcessorInfo();
122     assert(I <= PI.NumRegisterFiles && "Unexpected register file index!");
123     const MCRegisterFileDesc &RFDesc = PI.RegisterFiles[I];
124     // Skip invalid register files.
125     if (!RFDesc.NumPhysRegs)
126       continue;
127
128     TempStream << "\n*  Register File #" << I;
129     TempStream << " -- " << StringRef(RFDesc.Name) << ':';
130     TempStream << "\n   Number of physical registers:     ";
131     if (!RFDesc.NumPhysRegs)
132       TempStream << "unbounded";
133     else
134       TempStream << RFDesc.NumPhysRegs;
135     TempStream << "\n   Total number of mappings created: "
136                << RFU.TotalMappings;
137     TempStream << "\n   Max number of mappings used:      "
138                << RFU.MaxUsedMappings << '\n';
139     const MoveEliminationInfo &MEI = MoveElimInfo[I];
140
141     if (MEI.TotalMoveEliminationCandidates) {
142       TempStream << "   Number of optimizable moves:      "
143                  << MEI.TotalMoveEliminationCandidates;
144       double EliminatedMovProportion = (double)MEI.TotalMovesEliminated /
145                                        MEI.TotalMoveEliminationCandidates *
146                                        100.0;
147       double ZeroMovProportion = (double)MEI.TotalMovesThatPropagateZero /
148                                  MEI.TotalMoveEliminationCandidates * 100.0;
149       TempStream << "\n   Number of moves eliminated:       "
150                  << MEI.TotalMovesEliminated << "  "
151                  << format("(%.1f%%)",
152                            floor((EliminatedMovProportion * 10) + 0.5) / 10);
153       TempStream << "\n   Number of zero moves:             "
154                  << MEI.TotalMovesThatPropagateZero << "  "
155                  << format("(%.1f%%)",
156                            floor((ZeroMovProportion * 10) + 0.5) / 10);
157       TempStream << "\n   Max moves eliminated per cycle:   "
158                  << MEI.MaxMovesEliminatedPerCycle << '\n';
159     }
160   }
161
162   TempStream.flush();
163   OS << Buffer;
164 }
165
166 } // namespace mca
167 } // namespace llvm