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