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
RegisterFileStatistics(const MCSubtargetInfo & sti)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
updateRegisterFileUsage(ArrayRef<unsigned> UsedPhysRegs)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
updateMoveElimInfo(const Instruction & Inst)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
onEvent(const HWInstructionEvent & Event)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
onCycleEnd()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
printView(raw_ostream & OS) const105 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
169