forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathDebugCounter.cpp
169 lines (144 loc) · 6.4 KB
/
DebugCounter.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//===- DebugCounter.cpp - Debug Counter Facilities ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "mlir/Debug/Counter.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
using namespace mlir;
using namespace mlir::tracing;
//===----------------------------------------------------------------------===//
// DebugCounter CommandLine Options
//===----------------------------------------------------------------------===//
namespace {
/// This struct contains command line options that can be used to initialize
/// various bits of a DebugCounter. This uses a struct wrapper to avoid the need
/// for global command line options.
struct DebugCounterOptions {
llvm::cl::list<std::string> counters{
"mlir-debug-counter",
llvm::cl::desc(
"Comma separated list of debug counter skip and count arguments"),
llvm::cl::CommaSeparated};
llvm::cl::opt<bool> printCounterInfo{
"mlir-print-debug-counter", llvm::cl::init(false), llvm::cl::Optional,
llvm::cl::desc("Print out debug counter information after all counters "
"have been accumulated")};
};
} // namespace
static llvm::ManagedStatic<DebugCounterOptions> clOptions;
//===----------------------------------------------------------------------===//
// DebugCounter
//===----------------------------------------------------------------------===//
DebugCounter::DebugCounter() { applyCLOptions(); }
DebugCounter::~DebugCounter() {
// Print information when destroyed, iff command line option is specified.
if (clOptions.isConstructed() && clOptions->printCounterInfo)
print(llvm::dbgs());
}
/// Add a counter for the given debug action tag. `countToSkip` is the number
/// of counter executions to skip before enabling execution of the action.
/// `countToStopAfter` is the number of executions of the counter to allow
/// before preventing the action from executing any more.
void DebugCounter::addCounter(StringRef actionTag, int64_t countToSkip,
int64_t countToStopAfter) {
assert(!counters.count(actionTag) &&
"a counter for the given action was already registered");
counters.try_emplace(actionTag, countToSkip, countToStopAfter);
}
void DebugCounter::operator()(llvm::function_ref<void()> transform,
const Action &action) {
if (shouldExecute(action.getTag()))
transform();
}
bool DebugCounter::shouldExecute(StringRef tag) {
auto counterIt = counters.find(tag);
if (counterIt == counters.end())
return true;
++counterIt->second.count;
// We only execute while the `countToSkip` is not smaller than `count`, and
// `countToStopAfter + countToSkip` is larger than `count`. Negative counters
// always execute.
if (counterIt->second.countToSkip < 0)
return true;
if (counterIt->second.countToSkip >= counterIt->second.count)
return false;
if (counterIt->second.countToStopAfter < 0)
return true;
return counterIt->second.countToStopAfter + counterIt->second.countToSkip >=
counterIt->second.count;
}
void DebugCounter::print(raw_ostream &os) const {
// Order the registered counters by name.
SmallVector<const llvm::StringMapEntry<Counter> *, 16> sortedCounters(
llvm::make_pointer_range(counters));
llvm::array_pod_sort(sortedCounters.begin(), sortedCounters.end(),
[](const decltype(sortedCounters)::value_type *lhs,
const decltype(sortedCounters)::value_type *rhs) {
return (*lhs)->getKey().compare((*rhs)->getKey());
});
os << "DebugCounter counters:\n";
for (const llvm::StringMapEntry<Counter> *counter : sortedCounters) {
os << llvm::left_justify(counter->getKey(), 32) << ": {"
<< counter->second.count << "," << counter->second.countToSkip << ","
<< counter->second.countToStopAfter << "}\n";
}
}
/// Register a set of useful command-line options that can be used to configure
/// various flags within the DebugCounter. These flags are used when
/// constructing a DebugCounter for initialization.
void DebugCounter::registerCLOptions() {
// Make sure that the options struct has been initialized.
*clOptions;
}
bool DebugCounter::isActivated() {
return clOptions->counters.getNumOccurrences() ||
clOptions->printCounterInfo.getNumOccurrences();
}
// This is called by the command line parser when it sees a value for the
// debug-counter option defined above.
void DebugCounter::applyCLOptions() {
if (!clOptions.isConstructed())
return;
for (StringRef arg : clOptions->counters) {
if (arg.empty())
continue;
// Debug counter arguments are expected to be in the form: `counter=value`.
auto [counterName, counterValueStr] = arg.split('=');
if (counterValueStr.empty()) {
llvm::errs() << "error: expected DebugCounter argument to have an `=` "
"separating the counter name and value, but the provided "
"argument was: `"
<< arg << "`\n";
llvm::report_fatal_error(
"Invalid DebugCounter command-line configuration");
}
// Extract the counter value.
int64_t counterValue;
if (counterValueStr.getAsInteger(0, counterValue)) {
llvm::errs() << "error: expected DebugCounter counter value to be "
"numeric, but got `"
<< counterValueStr << "`\n";
llvm::report_fatal_error(
"Invalid DebugCounter command-line configuration");
}
// Now we need to see if this is the skip or the count, remove the suffix,
// and add it to the counter values.
if (counterName.consume_back("-skip")) {
counters[counterName].countToSkip = counterValue;
} else if (counterName.consume_back("-count")) {
counters[counterName].countToStopAfter = counterValue;
} else {
llvm::errs() << "error: expected DebugCounter counter name to end with "
"either `-skip` or `-count`, but got`"
<< counterName << "`\n";
llvm::report_fatal_error(
"Invalid DebugCounter command-line configuration");
}
}
}