LLVM 20.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"
49#include "llvm/Support/Debug.h"
50#include <string>
51
52namespace llvm {
53
54class raw_ostream;
55
57public:
58 struct Chunk {
59 int64_t Begin;
60 int64_t End;
62 bool contains(int64_t Idx) { return Idx >= Begin && Idx <= End; }
63 };
64
66
67 /// Return true on parsing error and print the error message on the
68 /// llvm::errs()
69 static bool parseChunks(StringRef Str, SmallVector<Chunk> &Res);
70
71 /// Returns a reference to the singleton instance.
72 static DebugCounter &instance();
73
74 // Used by the command line option parser to push a new value it parsed.
75 void push_back(const std::string &);
76
77 // Register a counter with the specified name.
78 //
79 // FIXME: Currently, counter registration is required to happen before command
80 // line option parsing. The main reason to register counters is to produce a
81 // nice list of them on the command line, but i'm not sure this is worth it.
83 return instance().addCounter(std::string(Name), std::string(Desc));
84 }
85 static bool shouldExecuteImpl(unsigned CounterName);
86
87 inline static bool shouldExecute(unsigned CounterName) {
88 if (!isCountingEnabled())
89 return true;
90 return shouldExecuteImpl(CounterName);
91 }
92
93 // Return true if a given counter had values set (either programatically or on
94 // the command line). This will return true even if those values are
95 // currently in a state where the counter will always execute.
96 static bool isCounterSet(unsigned ID) {
97 return instance().Counters[ID].IsSet;
98 }
99
101 int64_t Count;
103 };
104
105 // Return the state of a counter. This only works for set counters.
106 static CounterState getCounterState(unsigned ID) {
107 auto &Us = instance();
108 auto Result = Us.Counters.find(ID);
109 assert(Result != Us.Counters.end() && "Asking about a non-set counter");
110 return {Result->second.Count, Result->second.CurrChunkIdx};
111 }
112
113 // Set a registered counter to a given state.
114 static void setCounterState(unsigned ID, CounterState State) {
115 auto &Us = instance();
116 auto &Counter = Us.Counters[ID];
117 Counter.Count = State.Count;
118 Counter.CurrChunkIdx = State.ChunkIdx;
119 }
120
121 // Dump or print the current counter set into llvm::dbgs().
122 LLVM_DUMP_METHOD void dump() const;
123
124 void print(raw_ostream &OS) const;
125
126 // Get the counter ID for a given named counter, or return 0 if none is found.
127 unsigned getCounterId(const std::string &Name) const {
129 }
130
131 // Return the number of registered counters.
132 unsigned int getNumCounters() const { return RegisteredCounters.size(); }
133
134 // Return the name and description of the counter with the given ID.
135 std::pair<std::string, std::string> getCounterInfo(unsigned ID) const {
136 return std::make_pair(RegisteredCounters[ID], Counters.lookup(ID).Desc);
137 }
138
139 // Iterate through the registered counters
142 return RegisteredCounters.begin();
143 }
145
146 // Force-enables counting all DebugCounters.
147 //
148 // Since DebugCounters are incompatible with threading (not only do they not
149 // make sense, but we'll also see data races), this should only be used in
150 // contexts where we're certain we won't spawn threads.
151 static void enableAllCounters() { instance().Enabled = true; }
152
153 static bool isCountingEnabled() {
154// Compile to nothing when debugging is off
155#ifdef NDEBUG
156 return false;
157#else
159#endif
160 }
161
162protected:
163 unsigned addCounter(const std::string &Name, const std::string &Desc) {
164 unsigned Result = RegisteredCounters.insert(Name);
165 Counters[Result] = {};
166 Counters[Result].Desc = Desc;
167 return Result;
168 }
169 // Struct to store counter info.
170 struct CounterInfo {
171 int64_t Count = 0;
173 bool IsSet = false;
174 std::string Desc;
176 };
177
180
181 // Whether we should do DebugCounting at all. DebugCounters aren't
182 // thread-safe, so this should always be false in multithreaded scenarios.
183 bool Enabled = false;
184
185 bool ShouldPrintCounter = false;
186
187 bool BreakOnLast = false;
188};
189
190#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC) \
191 static const unsigned VARNAME = \
192 DebugCounter::registerCounter(COUNTERNAME, DESC)
193
194} // namespace llvm
195#endif
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:533
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
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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:106
static void printChunks(raw_ostream &OS, ArrayRef< Chunk >)
CounterVector::const_iterator end() const
Definition: DebugCounter.h:144
CounterVector::const_iterator begin() const
Definition: DebugCounter.h:141
DenseMap< unsigned, CounterInfo > Counters
Definition: DebugCounter.h:178
static bool isCounterSet(unsigned ID)
Definition: DebugCounter.h:96
static bool shouldExecute(unsigned CounterName)
Definition: DebugCounter.h:87
CounterVector RegisteredCounters
Definition: DebugCounter.h:179
std::pair< std::string, std::string > getCounterInfo(unsigned ID) const
Definition: DebugCounter.h:135
void push_back(const std::string &)
static bool isCountingEnabled()
Definition: DebugCounter.h:153
unsigned getCounterId(const std::string &Name) const
Definition: DebugCounter.h:127
static bool shouldExecuteImpl(unsigned CounterName)
static unsigned registerCounter(StringRef Name, StringRef Desc)
Definition: DebugCounter.h:82
UniqueVector< std::string > CounterVector
Definition: DebugCounter.h:140
unsigned addCounter(const std::string &Name, const std::string &Desc)
Definition: DebugCounter.h:163
static void enableAllCounters()
Definition: DebugCounter.h:151
static bool parseChunks(StringRef Str, SmallVector< Chunk > &Res)
Return true on parsing error and print the error message on the llvm::errs()
static DebugCounter & instance()
Returns a reference to the singleton instance.
void print(raw_ostream &OS) const
LLVM_DUMP_METHOD void dump() const
static void setCounterState(unsigned ID, CounterState State)
Definition: DebugCounter.h:114
unsigned int getNumCounters() const
Definition: DebugCounter.h:132
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
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:52
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
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.
void print(llvm::raw_ostream &OS)
bool contains(int64_t Idx)
Definition: DebugCounter.h:62
SmallVector< Chunk > Chunks
Definition: DebugCounter.h:175