1 //===--------------------- RegisterFileStatistics.cpp -----------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file implements the RegisterFileStatistics interface.
12 //===----------------------------------------------------------------------===//
14 #include "Views/RegisterFileStatistics.h"
15 #include "llvm/Support/Format.h"
20 RegisterFileStatistics::RegisterFileStatistics(const MCSubtargetInfo
&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
);
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);
40 PRFUsage
.resize(NumRegFiles
);
41 std::fill(PRFUsage
.begin(), PRFUsage
.end(), RFUEmpty
);
43 MoveElimInfo
.resize(NumRegFiles
);
44 std::fill(MoveElimInfo
.begin(), MoveElimInfo
.end(), MEIEmpty
);
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
;
55 std::max(RFU
.MaxUsedMappings
, RFU
.CurrentlyUsedMappings
);
59 void RegisterFileStatistics::updateMoveElimInfo(const Instruction
&Inst
) {
60 if (!Inst
.isOptimizableMove())
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];
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
++;
77 void RegisterFileStatistics::onEvent(const HWInstructionEvent
&Event
) {
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
];
87 case HWInstructionEvent::Dispatched
: {
88 const auto &DE
= static_cast<const HWInstructionDispatchedEvent
&>(Event
);
89 updateRegisterFileUsage(DE
.UsedPhysRegs
);
90 updateMoveElimInfo(*DE
.IR
.getInstruction());
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;
104 void RegisterFileStatistics::printView(raw_ostream
&OS
) const {
106 raw_string_ostream
TempStream(Buffer
);
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';
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
)
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";
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
];
141 if (MEI
.TotalMoveEliminationCandidates
) {
142 TempStream
<< " Number of optimizable moves: "
143 << MEI
.TotalMoveEliminationCandidates
;
144 double EliminatedMovProportion
= (double)MEI
.TotalMovesEliminated
/
145 MEI
.TotalMoveEliminationCandidates
*
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';