MLIR 22.0.0git
PassStatistics.cpp
Go to the documentation of this file.
1//===- PassStatistics.cpp -------------------------------------------------===//
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
9#include "PassDetail.h"
11#include "llvm/ADT/StringExtras.h"
12#include "llvm/Support/Format.h"
13
14using namespace mlir;
15using namespace mlir::detail;
16
17constexpr StringLiteral kPassStatsDescription =
18 "... Pass statistics report ...";
19
20namespace {
21/// Information pertaining to a specific statistic.
22struct Statistic {
23 const char *name, *desc;
24 uint64_t value;
25};
26} // namespace
27
28/// Utility to print a pass entry in the statistics output.
29static void printPassEntry(raw_ostream &os, unsigned indent, StringRef pass,
30 MutableArrayRef<Statistic> stats = {}) {
31 os.indent(indent) << pass << "\n";
32 if (stats.empty())
33 return;
34
35 // Make sure to sort the statistics by name.
36 llvm::array_pod_sort(
37 stats.begin(), stats.end(), [](const auto *lhs, const auto *rhs) {
38 return StringRef{lhs->name}.compare(StringRef{rhs->name});
39 });
40
41 // Collect the largest name and value length from each of the statistics.
42 size_t largestName = 0, largestValue = 0;
43 for (auto &stat : stats) {
44 largestName = std::max(largestName, (size_t)strlen(stat.name));
45 largestValue =
46 std::max(largestValue, (size_t)llvm::utostr(stat.value).size());
47 }
48
49 // Print each of the statistics.
50 for (auto &stat : stats) {
51 os.indent(indent + 2) << llvm::format("(S) %*u %-*s - %s\n", largestValue,
52 stat.value, largestName, stat.name,
53 stat.desc);
54 }
55}
56
57/// Print the statistics results in a list form, where each pass is sorted by
58/// name.
60 llvm::StringMap<std::vector<Statistic>> mergedStats;
61 std::function<void(Pass *)> addStats = [&](Pass *pass) {
62 auto *adaptor = dyn_cast<OpToOpPassAdaptor>(pass);
63
64 // If this is not an adaptor, add the stats to the list if there are any.
65 if (!adaptor) {
66#if LLVM_ENABLE_STATS
67 auto statistics = pass->getStatistics();
68 if (statistics.empty())
69 return;
70
71 auto &passEntry = mergedStats[pass->getName()];
72 if (passEntry.empty()) {
73 for (Pass::Statistic *it : pass->getStatistics())
74 passEntry.push_back({it->getName(), it->getDesc(), it->getValue()});
75 } else {
76 for (auto [idx, statistic] : llvm::enumerate(pass->getStatistics()))
77 passEntry[idx].value += statistic->getValue();
78 }
79#endif
80 return;
81 }
82
83 // Otherwise, recursively add each of the children.
84 for (auto &mgr : adaptor->getPassManagers())
85 for (Pass &pass : mgr.getPasses())
86 addStats(&pass);
87 };
88 for (Pass &pass : pm.getPasses())
89 addStats(&pass);
90
91 // Sort the statistics by pass name and then by record name.
92 auto passAndStatistics =
93 llvm::to_vector<16>(llvm::make_pointer_range(mergedStats));
94 llvm::array_pod_sort(passAndStatistics.begin(), passAndStatistics.end(),
95 [](const decltype(passAndStatistics)::value_type *lhs,
96 const decltype(passAndStatistics)::value_type *rhs) {
97 return (*lhs)->getKey().compare((*rhs)->getKey());
98 });
99
100 // Print the timing information sequentially.
101 for (auto &statData : passAndStatistics)
102 printPassEntry(os, /*indent=*/2, statData->first(), statData->second);
103}
104
105/// Print the results in pipeline mode that mirrors the internal pass manager
106/// structure.
108#if LLVM_ENABLE_STATS
109 std::function<void(unsigned, Pass *)> printPass = [&](unsigned indent,
110 Pass *pass) {
111 if (auto *adaptor = dyn_cast<OpToOpPassAdaptor>(pass)) {
112 // If this adaptor has more than one internal pipeline, print an entry for
113 // it.
114 auto mgrs = adaptor->getPassManagers();
115 if (mgrs.size() > 1) {
116 printPassEntry(os, indent, adaptor->getAdaptorName());
117 indent += 2;
118 }
119
120 // Print each of the children passes.
121 for (OpPassManager &mgr : mgrs) {
122 auto name = ("'" + mgr.getOpAnchorName() + "' Pipeline").str();
123 printPassEntry(os, indent, name);
124 for (Pass &pass : mgr.getPasses())
125 printPass(indent + 2, &pass);
126 }
127 return;
128 }
129
130 // Otherwise, we print the statistics for this pass.
131 std::vector<Statistic> stats;
132 for (Pass::Statistic *stat : pass->getStatistics())
133 stats.push_back({stat->getName(), stat->getDesc(), stat->getValue()});
134 printPassEntry(os, indent, pass->getName(), stats);
135 };
136 for (Pass &pass : pm.getPasses())
137 printPass(/*indent=*/0, &pass);
138#endif
139}
140
141static void printStatistics(OpPassManager &pm, PassDisplayMode displayMode) {
142 auto os = llvm::CreateInfoOutputFile();
143
144 // Print the stats header.
145 *os << "===" << std::string(73, '-') << "===\n";
146 // Figure out how many spaces for the description name.
147 unsigned padding = (80 - kPassStatsDescription.size()) / 2;
148 os->indent(padding) << kPassStatsDescription << '\n';
149 *os << "===" << std::string(73, '-') << "===\n";
150
151 // Defer to a specialized printer for each display mode.
152 switch (displayMode) {
154 printResultsAsList(*os, pm);
155 break;
157 printResultsAsPipeline(*os, pm);
158 break;
159 }
160 *os << "\n";
161 os->flush();
162}
163
164//===----------------------------------------------------------------------===//
165// PassStatistics
166//===----------------------------------------------------------------------===//
167
168Pass::Statistic::Statistic(Pass *owner, const char *name,
169 const char *description)
170 : llvm::Statistic{/*DebugType=*/"", name, description} {
171#if LLVM_ENABLE_STATS
172 // Always set the 'initialized' bit to true so that this statistic isn't
173 // placed in the static registry.
174 // TODO: This is sort of hack as `llvm::Statistic`s can't be setup to avoid
175 // automatic registration with the global registry. We should either add
176 // support for this in LLVM, or just write our own statistics classes.
177 Initialized = true;
178#endif
179
180 // Register this statistic with the parent.
181 owner->statistics.push_back(this);
182}
183
184auto Pass::Statistic::operator=(unsigned value) -> Statistic & {
185 llvm::Statistic::operator=(value);
186 return *this;
187}
188
189//===----------------------------------------------------------------------===//
190// PassManager
191//===----------------------------------------------------------------------===//
192
193/// Merge the pass statistics of this class into 'other'.
195 auto passes = getPasses(), otherPasses = other.getPasses();
196
197 for (auto passPair : llvm::zip(passes, otherPasses)) {
198 Pass &pass = std::get<0>(passPair), &otherPass = std::get<1>(passPair);
199
200 // If this is an adaptor, then recursively merge the pass managers.
201 if (auto *adaptorPass = dyn_cast<OpToOpPassAdaptor>(&pass)) {
202 auto *otherAdaptorPass = cast<OpToOpPassAdaptor>(&otherPass);
203 for (auto mgrs : llvm::zip(adaptorPass->getPassManagers(),
204 otherAdaptorPass->getPassManagers()))
205 std::get<0>(mgrs).mergeStatisticsInto(std::get<1>(mgrs));
206 continue;
207 }
208 // Otherwise, merge the statistics for the current pass.
209 assert(pass.statistics.size() == otherPass.statistics.size());
210 for (unsigned i = 0, e = pass.statistics.size(); i != e; ++i) {
211 assert(pass.statistics[i]->getName() ==
212 StringRef(otherPass.statistics[i]->getName()));
213 *otherPass.statistics[i] += *pass.statistics[i];
214 *pass.statistics[i] = 0;
215 }
216 }
217}
218
219/// Prepare the statistics of passes within the given pass manager for
220/// consumption(e.g. dumping).
222 for (Pass &pass : pm.getPasses()) {
223 OpToOpPassAdaptor *adaptor = dyn_cast<OpToOpPassAdaptor>(&pass);
224 if (!adaptor)
225 continue;
226 MutableArrayRef<OpPassManager> nestedPms = adaptor->getPassManagers();
227
228 // Merge the statistics from the async pass managers into the main nested
229 // pass managers. Prepare recursively before merging.
230 for (auto &asyncPM : adaptor->getParallelPassManagers()) {
231 for (unsigned i = 0, e = asyncPM.size(); i != e; ++i) {
232 prepareStatistics(asyncPM[i]);
233 asyncPM[i].mergeStatisticsInto(nestedPms[i]);
234 }
235 }
236
237 // Prepare the statistics of each of the nested passes.
238 for (OpPassManager &nestedPM : nestedPms)
239 prepareStatistics(nestedPM);
240 }
241}
242
243/// Dump the statistics of the passes within this pass manager.
244void PassManager::dumpStatistics() {
245 prepareStatistics(*this);
246 printStatistics(*this, *passStatisticsMode);
247}
248
249/// Dump the statistics for each pass after running.
251 passStatisticsMode = displayMode;
252}
lhs
static void printResultsAsList(raw_ostream &os, OpPassManager &pm)
Print the statistics results in a list form, where each pass is sorted by name.
static void printResultsAsPipeline(raw_ostream &os, OpPassManager &pm)
Print the results in pipeline mode that mirrors the internal pass manager structure.
static void printStatistics(OpPassManager &pm, PassDisplayMode displayMode)
static void printPassEntry(raw_ostream &os, unsigned indent, StringRef pass, MutableArrayRef< Statistic > stats={})
Utility to print a pass entry in the statistics output.
static void prepareStatistics(OpPassManager &pm)
Prepare the statistics of passes within the given pass manager for consumption(e.g.
constexpr StringLiteral kPassStatsDescription
This class represents a pass manager that runs passes on either a specific operation type,...
Definition PassManager.h:46
void mergeStatisticsInto(OpPassManager &other)
Merge the pass statistics of this class into 'other'.
OpPassManager(Nesting nesting=Nesting::Explicit)
Construct a new op-agnostic ("any") pass manager with the given operation type and nesting behavior.
Definition Pass.cpp:347
friend class Pass
iterator_range< pass_iterator > getPasses()
Definition PassManager.h:79
void enableStatistics(PassDisplayMode displayMode=PassDisplayMode::Pipeline)
Prompts the pass manager to print the statistics collected for each of the held passes after each cal...
This class represents a single pass statistic.
Definition Pass.h:133
Statistic(Pass *owner, const char *name, const char *description)
The statistic is initialized by the pass owner, a name, and a description.
Statistic & operator=(unsigned value)
Assign the statistic to the given value.
The abstract base pass class.
Definition Pass.h:51
Pass(TypeID passID, std::optional< StringRef > opName=std::nullopt)
Definition Pass.h:163
An adaptor pass used to run operation passes over nested operations.
Definition PassDetail.h:26
MutableArrayRef< OpPassManager > getPassManagers()
Returns the pass managers held by this adaptor.
Definition PassDetail.h:47
MutableArrayRef< SmallVector< OpPassManager, 1 > > getParallelPassManagers()
Return the async pass managers held by this parallel adaptor.
Definition PassDetail.h:54
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition CallGraph.h:229
AttrTypeReplacer.
Include the generated interface declarations.
PassDisplayMode
An enum describing the different display modes for the information within the pass manager.