1 //===--------------------- RegisterFileStatistics.cpp -----------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// This file implements the RegisterFileStatistics interface.
13 //===----------------------------------------------------------------------===//
15 #include "Views/RegisterFileStatistics.h"
16 #include "llvm/Support/Format.h"
21 RegisterFileStatistics::RegisterFileStatistics(const MCSubtargetInfo &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);
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);
41 PRFUsage.resize(NumRegFiles);
42 std::fill(PRFUsage.begin(), PRFUsage.end(), RFUEmpty);
44 MoveElimInfo.resize(NumRegFiles);
45 std::fill(MoveElimInfo.begin(), MoveElimInfo.end(), MEIEmpty);
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;
56 std::max(RFU.MaxUsedMappings, RFU.CurrentlyUsedMappings);
60 void RegisterFileStatistics::updateMoveElimInfo(const Instruction &Inst) {
61 if (!Inst.isOptimizableMove())
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];
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++;
78 void RegisterFileStatistics::onEvent(const HWInstructionEvent &Event) {
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];
88 case HWInstructionEvent::Dispatched: {
89 const auto &DE = static_cast<const HWInstructionDispatchedEvent &>(Event);
90 updateRegisterFileUsage(DE.UsedPhysRegs);
91 updateMoveElimInfo(*DE.IR.getInstruction());
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;
105 void RegisterFileStatistics::printView(raw_ostream &OS) const {
107 raw_string_ostream TempStream(Buffer);
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';
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)
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";
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];
142 if (MEI.TotalMoveEliminationCandidates) {
143 TempStream << " Number of optimizable moves: "
144 << MEI.TotalMoveEliminationCandidates;
145 double EliminatedMovProportion = (double)MEI.TotalMovesEliminated /
146 MEI.TotalMoveEliminationCandidates *
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';