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
17namespace llvm {
18namespace mca {
19
20RegisterFileStatistics::RegisterFileStatistics(const MCSubtargetInfo &sti)
21 : STI(sti) {
22 const MCSchedModel &SM = STI.getSchedModel();
23 RegisterFileUsage RFUEmpty = {.TotalMappings: 0, .MaxUsedMappings: 0, .CurrentlyUsedMappings: 0};
24 MoveEliminationInfo MEIEmpty = {.TotalMoveEliminationCandidates: 0, .TotalMovesEliminated: 0, .TotalMovesThatPropagateZero: 0, .MaxMovesEliminatedPerCycle: 0, .CurrentMovesEliminated: 0};
25 if (!SM.hasExtraProcessorInfo()) {
26 // Assume a single register file.
27 PRFUsage.emplace_back(Args&: RFUEmpty);
28 MoveElimInfo.emplace_back(Args&: 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(a: PI.NumRegisterFiles, b: 1U);
39
40 PRFUsage.resize(N: NumRegFiles);
41 std::fill(first: PRFUsage.begin(), last: PRFUsage.end(), value: RFUEmpty);
42
43 MoveElimInfo.resize(N: NumRegFiles);
44 std::fill(first: MoveElimInfo.begin(), last: MoveElimInfo.end(), value: MEIEmpty);
45}
46
47void 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(a: RFU.MaxUsedMappings, b: RFU.CurrentlyUsedMappings);
56 }
57}
58
59void RegisterFileStatistics::updateMoveElimInfo(const Instruction &Inst) {
60 if (!Inst.isOptimizableMove())
61 return;
62
63 if (Inst.getDefs().size() != Inst.getUses().size())
64 return;
65
66 for (size_t I = 0, E = Inst.getDefs().size(); I < E; ++I) {
67 const WriteState &WS = Inst.getDefs()[I];
68 const ReadState &RS = Inst.getUses()[E - (I + 1)];
69
70 MoveEliminationInfo &Info =
71 MoveElimInfo[Inst.getDefs()[0].getRegisterFileID()];
72 Info.TotalMoveEliminationCandidates++;
73 if (WS.isEliminated())
74 Info.CurrentMovesEliminated++;
75 if (WS.isWriteZero() && RS.isReadZero())
76 Info.TotalMovesThatPropagateZero++;
77 }
78}
79
80void RegisterFileStatistics::onEvent(const HWInstructionEvent &Event) {
81 switch (Event.Type) {
82 default:
83 break;
84 case HWInstructionEvent::Retired: {
85 const auto &RE = static_cast<const HWInstructionRetiredEvent &>(Event);
86 for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I)
87 PRFUsage[I].CurrentlyUsedMappings -= RE.FreedPhysRegs[I];
88 break;
89 }
90 case HWInstructionEvent::Dispatched: {
91 const auto &DE = static_cast<const HWInstructionDispatchedEvent &>(Event);
92 updateRegisterFileUsage(UsedPhysRegs: DE.UsedPhysRegs);
93 updateMoveElimInfo(Inst: *DE.IR.getInstruction());
94 }
95 }
96}
97
98void RegisterFileStatistics::onCycleEnd() {
99 for (MoveEliminationInfo &MEI : MoveElimInfo) {
100 unsigned &CurrentMax = MEI.MaxMovesEliminatedPerCycle;
101 CurrentMax = std::max(a: CurrentMax, b: MEI.CurrentMovesEliminated);
102 MEI.TotalMovesEliminated += MEI.CurrentMovesEliminated;
103 MEI.CurrentMovesEliminated = 0;
104 }
105}
106
107void RegisterFileStatistics::printView(raw_ostream &OS) const {
108 std::string Buffer;
109 raw_string_ostream TempStream(Buffer);
110
111 TempStream << "\n\nRegister File statistics:";
112 const RegisterFileUsage &GlobalUsage = PRFUsage[0];
113 TempStream << "\nTotal number of mappings created: "
114 << GlobalUsage.TotalMappings;
115 TempStream << "\nMax number of mappings used: "
116 << GlobalUsage.MaxUsedMappings << '\n';
117
118 for (unsigned I = 1, E = PRFUsage.size(); I < E; ++I) {
119 const RegisterFileUsage &RFU = PRFUsage[I];
120 // Obtain the register file descriptor from the scheduling model.
121 assert(STI.getSchedModel().hasExtraProcessorInfo() &&
122 "Unable to find register file info!");
123 const MCExtraProcessorInfo &PI =
124 STI.getSchedModel().getExtraProcessorInfo();
125 assert(I <= PI.NumRegisterFiles && "Unexpected register file index!");
126 const MCRegisterFileDesc &RFDesc = PI.RegisterFiles[I];
127 // Skip invalid register files.
128 if (!RFDesc.NumPhysRegs)
129 continue;
130
131 TempStream << "\n* Register File #" << I;
132 TempStream << " -- " << StringRef(RFDesc.Name) << ':';
133 TempStream << "\n Number of physical registers: ";
134 if (!RFDesc.NumPhysRegs)
135 TempStream << "unbounded";
136 else
137 TempStream << RFDesc.NumPhysRegs;
138 TempStream << "\n Total number of mappings created: "
139 << RFU.TotalMappings;
140 TempStream << "\n Max number of mappings used: "
141 << RFU.MaxUsedMappings << '\n';
142 const MoveEliminationInfo &MEI = MoveElimInfo[I];
143
144 if (MEI.TotalMoveEliminationCandidates) {
145 TempStream << " Number of optimizable moves: "
146 << MEI.TotalMoveEliminationCandidates;
147 double EliminatedMovProportion = (double)MEI.TotalMovesEliminated /
148 MEI.TotalMoveEliminationCandidates *
149 100.0;
150 double ZeroMovProportion = (double)MEI.TotalMovesThatPropagateZero /
151 MEI.TotalMoveEliminationCandidates * 100.0;
152 TempStream << "\n Number of moves eliminated: "
153 << MEI.TotalMovesEliminated << " "
154 << format(Fmt: "(%.1f%%)",
155 Vals: floor(x: (EliminatedMovProportion * 10) + 0.5) / 10);
156 TempStream << "\n Number of zero moves: "
157 << MEI.TotalMovesThatPropagateZero << " "
158 << format(Fmt: "(%.1f%%)",
159 Vals: floor(x: (ZeroMovProportion * 10) + 0.5) / 10);
160 TempStream << "\n Max moves eliminated per cycle: "
161 << MEI.MaxMovesEliminatedPerCycle << '\n';
162 }
163 }
164
165 TempStream.flush();
166 OS << Buffer;
167}
168
169} // namespace mca
170} // namespace llvm
171

source code of llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp