forked from OSchip/llvm-project
163 lines
6.3 KiB
C++
163 lines
6.3 KiB
C++
//===- 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/Support/DebugCounter.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/Format.h"
|
|
#include "llvm/Support/ManagedStatic.h"
|
|
|
|
using namespace mlir;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// 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::ZeroOrMore};
|
|
|
|
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);
|
|
}
|
|
|
|
// Register a counter with the specified name.
|
|
FailureOr<bool> DebugCounter::shouldExecute(StringRef tag,
|
|
StringRef description) {
|
|
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() {
|
|
#ifndef NDEBUG
|
|
// Make sure that the options struct has been initialized.
|
|
*clOptions;
|
|
#endif
|
|
}
|
|
|
|
// 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`.
|
|
StringRef counterName, counterValueStr;
|
|
std::tie(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");
|
|
}
|
|
}
|
|
}
|