LLVM 22.0.0git
DebugCounter.h
Go to the documentation of this file.
1//===- llvm/Support/DebugCounter.h - Debug counter support ------*- 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/// This file provides an implementation of debug counters. Debug
10/// counters are a tool that let you narrow down a miscompilation to a specific
11/// thing happening.
12///
13/// To give a use case: Imagine you have a file, very large, and you
14/// are trying to understand the minimal transformation that breaks it. Bugpoint
15/// and bisection is often helpful here in narrowing it down to a specific pass,
16/// but it's still a very large file, and a very complicated pass to try to
17/// debug. That is where debug counting steps in. You can instrument the pass
18/// with a debug counter before it does a certain thing, and depending on the
19/// counts, it will either execute that thing or not. The debug counter itself
20/// consists of a list of chunks (inclusive numeric ranges). `shouldExecute`
21/// returns true iff the list is empty or the current count is in one of the
22/// chunks.
23///
24/// Note that a counter set to a negative number will always execute. For a
25/// concrete example, during predicateinfo creation, the renaming pass replaces
26/// each use with a renamed use.
27////
28/// If I use DEBUG_COUNTER to create a counter called "predicateinfo", and
29/// variable name RenameCounter, and then instrument this renaming with a debug
30/// counter, like so:
31///
32/// if (!DebugCounter::shouldExecute(RenameCounter)
33/// <continue or return or whatever not executing looks like>
34///
35/// Now I can, from the command line, make it rename or not rename certain uses
36/// by setting the chunk list.
37/// So for example
38/// bin/opt -debug-counter=predicateinfo=47
39/// will skip renaming the first 47 uses, then rename one, then skip the rest.
40//===----------------------------------------------------------------------===//
41
42#ifndef LLVM_SUPPORT_DEBUGCOUNTER_H
43#define LLVM_SUPPORT_DEBUGCOUNTER_H
44
45#include "llvm/ADT/ArrayRef.h"
46#include "llvm/ADT/DenseMap.h"
47#include "llvm/ADT/StringRef.h"
50#include "llvm/Support/Debug.h"
51#include <string>
52
53namespace llvm {
54
55class raw_ostream;
56
58public:
59 struct Chunk {
60 int64_t Begin;
61 int64_t End;
63 bool contains(int64_t Idx) const { return Idx >= Begin && Idx <= End; }
64 };
65
67
68 /// Return true on parsing error and print the error message on the
69 /// llvm::errs()
70 LLVM_ABI static bool parseChunks(StringRef Str, SmallVector<Chunk> &Res);
71
72 /// Returns a reference to the singleton instance.
74
75 // Used by the command line option parser to push a new value it parsed.
76 LLVM_ABI void push_back(const std::string &);
77
78 // Register a counter with the specified name.
79 //
80 // FIXME: Currently, counter registration is required to happen before command
81 // line option parsing. The main reason to register counters is to produce a
82 // nice list of them on the command line, but i'm not sure this is worth it.
84 return instance().addCounter(std::string(Name), std::string(Desc));
85 }
86 LLVM_ABI static bool shouldExecuteImpl(unsigned CounterName);
87
88 inline static bool shouldExecute(unsigned CounterName) {
89 if (!isCountingEnabled())
90 return true;
91 return shouldExecuteImpl(CounterName);
92 }
93
94 // Return true if a given counter had values set (either programatically or on
95 // the command line). This will return true even if those values are
96 // currently in a state where the counter will always execute.
97 static bool isCounterSet(unsigned ID) {
98 return instance().Counters[ID].IsSet;
99 }
100
102 int64_t Count;
104 };
105
106 // Return the state of a counter. This only works for set counters.
107 static CounterState getCounterState(unsigned ID) {
108 auto &Us = instance();
109 auto Result = Us.Counters.find(ID);
110 assert(Result != Us.Counters.end() && "Asking about a non-set counter");
111 return {Result->second.Count, Result->second.CurrChunkIdx};
112 }
113
114 // Set a registered counter to a given state.
115 static void setCounterState(unsigned ID, CounterState State) {
116 auto &Us = instance();
117 auto &Counter = Us.Counters[ID];
118 Counter.Count = State.Count;
119 Counter.CurrChunkIdx = State.ChunkIdx;
120 }
121
122#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
123 // Dump or print the current counter set into llvm::dbgs().
124 LLVM_DUMP_METHOD void dump() const;
125#endif
126
127 LLVM_ABI void print(raw_ostream &OS) const;
128
129 // Get the counter ID for a given named counter, or return 0 if none is found.
130 unsigned getCounterId(const std::string &Name) const {
132 }
133
134 // Return the number of registered counters.
135 unsigned int getNumCounters() const { return RegisteredCounters.size(); }
136
137 // Return the name and description of the counter with the given ID.
138 std::pair<std::string, std::string> getCounterInfo(unsigned ID) const {
139 return std::make_pair(RegisteredCounters[ID], Counters.lookup(ID).Desc);
140 }
141
142 // Iterate through the registered counters
145 return RegisteredCounters.begin();
146 }
148
149 // Force-enables counting all DebugCounters.
150 //
151 // Since DebugCounters are incompatible with threading (not only do they not
152 // make sense, but we'll also see data races), this should only be used in
153 // contexts where we're certain we won't spawn threads.
154 static void enableAllCounters() { instance().Enabled = true; }
155
156 static bool isCountingEnabled() {
157// Compile to nothing when debugging is off
158#ifdef NDEBUG
159 return false;
160#else
162#endif
163 }
164
165protected:
166 unsigned addCounter(const std::string &Name, const std::string &Desc) {
167 unsigned Result = RegisteredCounters.insert(Name);
168 auto &C = Counters[Result];
169 C = {};
170 C.Desc = Desc;
171 return Result;
172 }
173 // Struct to store counter info.
174 struct CounterInfo {
175 int64_t Count = 0;
177 bool IsSet = false;
178 std::string Desc;
180 };
181
184
185 // Whether we should do DebugCounting at all. DebugCounters aren't
186 // thread-safe, so this should always be false in multithreaded scenarios.
187 bool Enabled = false;
188
189 bool ShouldPrintCounter = false;
190
191 bool BreakOnLast = false;
192};
193
194#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC) \
195 static const unsigned VARNAME = \
196 DebugCounter::registerCounter(COUNTERNAME, DESC)
197
198} // namespace llvm
199#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition: Compiler.h:213
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:638
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
std::string Name
raw_pwrite_stream & OS
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
static CounterState getCounterState(unsigned ID)
Definition: DebugCounter.h:107
static LLVM_ABI void printChunks(raw_ostream &OS, ArrayRef< Chunk >)
CounterVector::const_iterator end() const
Definition: DebugCounter.h:147
CounterVector::const_iterator begin() const
Definition: DebugCounter.h:144
DenseMap< unsigned, CounterInfo > Counters
Definition: DebugCounter.h:182
static bool isCounterSet(unsigned ID)
Definition: DebugCounter.h:97
static bool shouldExecute(unsigned CounterName)
Definition: DebugCounter.h:88
CounterVector RegisteredCounters
Definition: DebugCounter.h:183
std::pair< std::string, std::string > getCounterInfo(unsigned ID) const
Definition: DebugCounter.h:138
LLVM_ABI void push_back(const std::string &)
static bool isCountingEnabled()
Definition: DebugCounter.h:156
unsigned getCounterId(const std::string &Name) const
Definition: DebugCounter.h:130
static LLVM_ABI bool shouldExecuteImpl(unsigned CounterName)
static unsigned registerCounter(StringRef Name, StringRef Desc)
Definition: DebugCounter.h:83
UniqueVector< std::string > CounterVector
Definition: DebugCounter.h:143
unsigned addCounter(const std::string &Name, const std::string &Desc)
Definition: DebugCounter.h:166
static void enableAllCounters()
Definition: DebugCounter.h:154
static LLVM_ABI bool parseChunks(StringRef Str, SmallVector< Chunk > &Res)
Return true on parsing error and print the error message on the llvm::errs()
static LLVM_ABI DebugCounter & instance()
Returns a reference to the singleton instance.
LLVM_ABI void print(raw_ostream &OS) const
LLVM_DUMP_METHOD void dump() const
static void setCounterState(unsigned ID, CounterState State)
Definition: DebugCounter.h:115
unsigned int getNumCounters() const
Definition: DebugCounter.h:135
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
UniqueVector - This class produces a sequential ID number (base 1) for each unique entry that is adde...
Definition: UniqueVector.h:24
typename VectorType::const_iterator const_iterator
Definition: UniqueVector.h:28
unsigned insert(const T &Entry)
insert - Append entry to the vector if it doesn't already exist.
Definition: UniqueVector.h:40
size_t size() const
size - Returns the number of entries in the vector.
Definition: UniqueVector.h:87
iterator end()
Return an iterator to the end of the vector.
Definition: UniqueVector.h:81
unsigned idFor(const T &Entry) const
idFor - return the ID for an existing entry.
Definition: UniqueVector.h:57
iterator begin()
Return an iterator to the start of the vector.
Definition: UniqueVector.h:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Op::Description Desc
Description of the encoding of one expression Op.
bool contains(int64_t Idx) const
Definition: DebugCounter.h:63
LLVM_ABI void print(llvm::raw_ostream &OS)
SmallVector< Chunk > Chunks
Definition: DebugCounter.h:179