110aa09f0SMatt Davis //===--------------------- RegisterFileStatistics.cpp -----------*- C++ -*-===//
210aa09f0SMatt Davis //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
610aa09f0SMatt Davis //
710aa09f0SMatt Davis //===----------------------------------------------------------------------===//
810aa09f0SMatt Davis /// \file
910aa09f0SMatt Davis ///
1010aa09f0SMatt Davis /// This file implements the RegisterFileStatistics interface.
1110aa09f0SMatt Davis ///
1210aa09f0SMatt Davis //===----------------------------------------------------------------------===//
1310aa09f0SMatt Davis
1410aa09f0SMatt Davis #include "Views/RegisterFileStatistics.h"
1510aa09f0SMatt Davis #include "llvm/Support/Format.h"
1610aa09f0SMatt Davis
175a8fd657SFangrui Song namespace llvm {
1810aa09f0SMatt Davis namespace mca {
1910aa09f0SMatt Davis
RegisterFileStatistics(const MCSubtargetInfo & sti)20db158be6SAndrea Di Biagio RegisterFileStatistics::RegisterFileStatistics(const MCSubtargetInfo &sti)
21b7f120f0SAndrea Di Biagio : STI(sti) {
2210aa09f0SMatt Davis const MCSchedModel &SM = STI.getSchedModel();
23fe3bc1b9SAndrea Di Biagio RegisterFileUsage RFUEmpty = {0, 0, 0};
24fe3bc1b9SAndrea Di Biagio MoveEliminationInfo MEIEmpty = {0, 0, 0, 0, 0};
2510aa09f0SMatt Davis if (!SM.hasExtraProcessorInfo()) {
2610aa09f0SMatt Davis // Assume a single register file.
27fe3bc1b9SAndrea Di Biagio PRFUsage.emplace_back(RFUEmpty);
28fe3bc1b9SAndrea Di Biagio MoveElimInfo.emplace_back(MEIEmpty);
2910aa09f0SMatt Davis return;
3010aa09f0SMatt Davis }
3110aa09f0SMatt Davis
3210aa09f0SMatt Davis // Initialize a RegisterFileUsage for every user defined register file, plus
3310aa09f0SMatt Davis // the default register file which is always at index #0.
3410aa09f0SMatt Davis const MCExtraProcessorInfo &PI = SM.getExtraProcessorInfo();
3510aa09f0SMatt Davis // There is always an "InvalidRegisterFile" entry in tablegen. That entry can
3610aa09f0SMatt Davis // be skipped. If there are no user defined register files, then reserve a
3710aa09f0SMatt Davis // single entry for the default register file at index #0.
3810aa09f0SMatt Davis unsigned NumRegFiles = std::max(PI.NumRegisterFiles, 1U);
39fe3bc1b9SAndrea Di Biagio
40fe3bc1b9SAndrea Di Biagio PRFUsage.resize(NumRegFiles);
41fe3bc1b9SAndrea Di Biagio std::fill(PRFUsage.begin(), PRFUsage.end(), RFUEmpty);
42fe3bc1b9SAndrea Di Biagio
43fe3bc1b9SAndrea Di Biagio MoveElimInfo.resize(NumRegFiles);
44fe3bc1b9SAndrea Di Biagio std::fill(MoveElimInfo.begin(), MoveElimInfo.end(), MEIEmpty);
45fe3bc1b9SAndrea Di Biagio }
46fe3bc1b9SAndrea Di Biagio
updateRegisterFileUsage(ArrayRef<unsigned> UsedPhysRegs)47fe3bc1b9SAndrea Di Biagio void RegisterFileStatistics::updateRegisterFileUsage(
48fe3bc1b9SAndrea Di Biagio ArrayRef<unsigned> UsedPhysRegs) {
49fe3bc1b9SAndrea Di Biagio for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I) {
50fe3bc1b9SAndrea Di Biagio RegisterFileUsage &RFU = PRFUsage[I];
51fe3bc1b9SAndrea Di Biagio unsigned NumUsedPhysRegs = UsedPhysRegs[I];
52fe3bc1b9SAndrea Di Biagio RFU.CurrentlyUsedMappings += NumUsedPhysRegs;
53fe3bc1b9SAndrea Di Biagio RFU.TotalMappings += NumUsedPhysRegs;
54fe3bc1b9SAndrea Di Biagio RFU.MaxUsedMappings =
55fe3bc1b9SAndrea Di Biagio std::max(RFU.MaxUsedMappings, RFU.CurrentlyUsedMappings);
56fe3bc1b9SAndrea Di Biagio }
57fe3bc1b9SAndrea Di Biagio }
58fe3bc1b9SAndrea Di Biagio
updateMoveElimInfo(const Instruction & Inst)59fe3bc1b9SAndrea Di Biagio void RegisterFileStatistics::updateMoveElimInfo(const Instruction &Inst) {
60fe3bc1b9SAndrea Di Biagio if (!Inst.isOptimizableMove())
61fe3bc1b9SAndrea Di Biagio return;
62fe3bc1b9SAndrea Di Biagio
63*de1843e5SAndrea Di Biagio if (Inst.getDefs().size() != Inst.getUses().size())
64*de1843e5SAndrea Di Biagio return;
65*de1843e5SAndrea Di Biagio
66*de1843e5SAndrea Di Biagio for (size_t I = 0, E = Inst.getDefs().size(); I < E; ++I) {
67*de1843e5SAndrea Di Biagio const WriteState &WS = Inst.getDefs()[I];
68*de1843e5SAndrea Di Biagio const ReadState &RS = Inst.getUses()[E - (I + 1)];
69fe3bc1b9SAndrea Di Biagio
70fe3bc1b9SAndrea Di Biagio MoveEliminationInfo &Info =
71fe3bc1b9SAndrea Di Biagio MoveElimInfo[Inst.getDefs()[0].getRegisterFileID()];
72fe3bc1b9SAndrea Di Biagio Info.TotalMoveEliminationCandidates++;
73fe3bc1b9SAndrea Di Biagio if (WS.isEliminated())
74fe3bc1b9SAndrea Di Biagio Info.CurrentMovesEliminated++;
75fe3bc1b9SAndrea Di Biagio if (WS.isWriteZero() && RS.isReadZero())
76fe3bc1b9SAndrea Di Biagio Info.TotalMovesThatPropagateZero++;
7710aa09f0SMatt Davis }
78*de1843e5SAndrea Di Biagio }
7910aa09f0SMatt Davis
onEvent(const HWInstructionEvent & Event)8010aa09f0SMatt Davis void RegisterFileStatistics::onEvent(const HWInstructionEvent &Event) {
8110aa09f0SMatt Davis switch (Event.Type) {
8210aa09f0SMatt Davis default:
8310aa09f0SMatt Davis break;
8410aa09f0SMatt Davis case HWInstructionEvent::Retired: {
8510aa09f0SMatt Davis const auto &RE = static_cast<const HWInstructionRetiredEvent &>(Event);
86fe3bc1b9SAndrea Di Biagio for (unsigned I = 0, E = PRFUsage.size(); I < E; ++I)
87fe3bc1b9SAndrea Di Biagio PRFUsage[I].CurrentlyUsedMappings -= RE.FreedPhysRegs[I];
8810aa09f0SMatt Davis break;
8910aa09f0SMatt Davis }
9010aa09f0SMatt Davis case HWInstructionEvent::Dispatched: {
9110aa09f0SMatt Davis const auto &DE = static_cast<const HWInstructionDispatchedEvent &>(Event);
92fe3bc1b9SAndrea Di Biagio updateRegisterFileUsage(DE.UsedPhysRegs);
93fe3bc1b9SAndrea Di Biagio updateMoveElimInfo(*DE.IR.getInstruction());
9410aa09f0SMatt Davis }
9510aa09f0SMatt Davis }
9610aa09f0SMatt Davis }
97fe3bc1b9SAndrea Di Biagio
onCycleEnd()98fe3bc1b9SAndrea Di Biagio void RegisterFileStatistics::onCycleEnd() {
99fe3bc1b9SAndrea Di Biagio for (MoveEliminationInfo &MEI : MoveElimInfo) {
100fe3bc1b9SAndrea Di Biagio unsigned &CurrentMax = MEI.MaxMovesEliminatedPerCycle;
101fe3bc1b9SAndrea Di Biagio CurrentMax = std::max(CurrentMax, MEI.CurrentMovesEliminated);
102fe3bc1b9SAndrea Di Biagio MEI.TotalMovesEliminated += MEI.CurrentMovesEliminated;
103fe3bc1b9SAndrea Di Biagio MEI.CurrentMovesEliminated = 0;
104fe3bc1b9SAndrea Di Biagio }
10510aa09f0SMatt Davis }
10610aa09f0SMatt Davis
printView(raw_ostream & OS) const10710aa09f0SMatt Davis void RegisterFileStatistics::printView(raw_ostream &OS) const {
10810aa09f0SMatt Davis std::string Buffer;
10910aa09f0SMatt Davis raw_string_ostream TempStream(Buffer);
11010aa09f0SMatt Davis
11110aa09f0SMatt Davis TempStream << "\n\nRegister File statistics:";
112fe3bc1b9SAndrea Di Biagio const RegisterFileUsage &GlobalUsage = PRFUsage[0];
11310aa09f0SMatt Davis TempStream << "\nTotal number of mappings created: "
11410aa09f0SMatt Davis << GlobalUsage.TotalMappings;
11510aa09f0SMatt Davis TempStream << "\nMax number of mappings used: "
11610aa09f0SMatt Davis << GlobalUsage.MaxUsedMappings << '\n';
11710aa09f0SMatt Davis
118fe3bc1b9SAndrea Di Biagio for (unsigned I = 1, E = PRFUsage.size(); I < E; ++I) {
119fe3bc1b9SAndrea Di Biagio const RegisterFileUsage &RFU = PRFUsage[I];
12010aa09f0SMatt Davis // Obtain the register file descriptor from the scheduling model.
12110aa09f0SMatt Davis assert(STI.getSchedModel().hasExtraProcessorInfo() &&
12210aa09f0SMatt Davis "Unable to find register file info!");
12310aa09f0SMatt Davis const MCExtraProcessorInfo &PI =
12410aa09f0SMatt Davis STI.getSchedModel().getExtraProcessorInfo();
12510aa09f0SMatt Davis assert(I <= PI.NumRegisterFiles && "Unexpected register file index!");
12610aa09f0SMatt Davis const MCRegisterFileDesc &RFDesc = PI.RegisterFiles[I];
12710aa09f0SMatt Davis // Skip invalid register files.
12810aa09f0SMatt Davis if (!RFDesc.NumPhysRegs)
12910aa09f0SMatt Davis continue;
13010aa09f0SMatt Davis
13110aa09f0SMatt Davis TempStream << "\n* Register File #" << I;
13210aa09f0SMatt Davis TempStream << " -- " << StringRef(RFDesc.Name) << ':';
13310aa09f0SMatt Davis TempStream << "\n Number of physical registers: ";
13410aa09f0SMatt Davis if (!RFDesc.NumPhysRegs)
13510aa09f0SMatt Davis TempStream << "unbounded";
13610aa09f0SMatt Davis else
13710aa09f0SMatt Davis TempStream << RFDesc.NumPhysRegs;
13810aa09f0SMatt Davis TempStream << "\n Total number of mappings created: "
13910aa09f0SMatt Davis << RFU.TotalMappings;
14010aa09f0SMatt Davis TempStream << "\n Max number of mappings used: "
14110aa09f0SMatt Davis << RFU.MaxUsedMappings << '\n';
142fe3bc1b9SAndrea Di Biagio const MoveEliminationInfo &MEI = MoveElimInfo[I];
143fe3bc1b9SAndrea Di Biagio
144fe3bc1b9SAndrea Di Biagio if (MEI.TotalMoveEliminationCandidates) {
145fe3bc1b9SAndrea Di Biagio TempStream << " Number of optimizable moves: "
146fe3bc1b9SAndrea Di Biagio << MEI.TotalMoveEliminationCandidates;
147fe3bc1b9SAndrea Di Biagio double EliminatedMovProportion = (double)MEI.TotalMovesEliminated /
148fe3bc1b9SAndrea Di Biagio MEI.TotalMoveEliminationCandidates *
149fe3bc1b9SAndrea Di Biagio 100.0;
150fe3bc1b9SAndrea Di Biagio double ZeroMovProportion = (double)MEI.TotalMovesThatPropagateZero /
151fe3bc1b9SAndrea Di Biagio MEI.TotalMoveEliminationCandidates * 100.0;
152fe3bc1b9SAndrea Di Biagio TempStream << "\n Number of moves eliminated: "
153fe3bc1b9SAndrea Di Biagio << MEI.TotalMovesEliminated << " "
154fe3bc1b9SAndrea Di Biagio << format("(%.1f%%)",
155fe3bc1b9SAndrea Di Biagio floor((EliminatedMovProportion * 10) + 0.5) / 10);
156fe3bc1b9SAndrea Di Biagio TempStream << "\n Number of zero moves: "
157fe3bc1b9SAndrea Di Biagio << MEI.TotalMovesThatPropagateZero << " "
158fe3bc1b9SAndrea Di Biagio << format("(%.1f%%)",
159fe3bc1b9SAndrea Di Biagio floor((ZeroMovProportion * 10) + 0.5) / 10);
160fe3bc1b9SAndrea Di Biagio TempStream << "\n Max moves eliminated per cycle: "
161fe3bc1b9SAndrea Di Biagio << MEI.MaxMovesEliminatedPerCycle << '\n';
162fe3bc1b9SAndrea Di Biagio }
16310aa09f0SMatt Davis }
16410aa09f0SMatt Davis
16510aa09f0SMatt Davis TempStream.flush();
16610aa09f0SMatt Davis OS << Buffer;
16710aa09f0SMatt Davis }
16810aa09f0SMatt Davis
16910aa09f0SMatt Davis } // namespace mca
1705a8fd657SFangrui Song } // namespace llvm
171