17
17
// / debug. That is where debug counting steps in. You can instrument the pass
18
18
// / with a debug counter before it does a certain thing, and depending on the
19
19
// / counts, it will either execute that thing or not. The debug counter itself
20
- // / consists of a skip and a count. Skip is the number of times shouldExecute
21
- // / needs to be called before it returns true. Count is the number of times to
22
- // / return true once Skip is 0. So a skip=47, count=2 ,would skip the first 47
23
- // / executions by returning false from shouldExecute, then execute twice, and
24
- // / then return false again.
25
- // / Note that a counter set to a negative number will always execute.
26
- // / For a concrete example, during predicateinfo creation, the renaming pass
27
- // / replaces each use with a renamed use.
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.
28
27
// //
29
28
// / If I use DEBUG_COUNTER to create a counter called "predicateinfo", and
30
29
// / variable name RenameCounter, and then instrument this renaming with a debug
34
33
// / <continue or return or whatever not executing looks like>
35
34
// /
36
35
// / Now I can, from the command line, make it rename or not rename certain uses
37
- // / by setting the skip and count .
36
+ // / by setting the chunk list .
38
37
// / So for example
39
- // / bin/opt -debug-counter=predicateinfo-skip =47,predicateinfo-count=1
38
+ // / bin/opt -debug-counter=predicateinfo=47
40
39
// / will skip renaming the first 47 uses, then rename one, then skip the rest.
41
40
// ===----------------------------------------------------------------------===//
42
41
43
42
#ifndef LLVM_SUPPORT_DEBUGCOUNTER_H
44
43
#define LLVM_SUPPORT_DEBUGCOUNTER_H
45
44
45
+ #include " llvm/ADT/ArrayRef.h"
46
46
#include " llvm/ADT/DenseMap.h"
47
47
#include " llvm/ADT/StringRef.h"
48
48
#include " llvm/ADT/UniqueVector.h"
@@ -55,6 +55,19 @@ class raw_ostream;
55
55
56
56
class DebugCounter {
57
57
public:
58
+ struct Chunk {
59
+ int64_t Begin;
60
+ int64_t End;
61
+ void print (llvm::raw_ostream &OS);
62
+ bool contains (int64_t Idx) { return Idx >= Begin && Idx <= End; }
63
+ };
64
+
65
+ static void printChunks (raw_ostream &OS, ArrayRef<Chunk>);
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
+
58
71
// / Returns a reference to the singleton instance.
59
72
static DebugCounter &instance ();
60
73
@@ -69,29 +82,12 @@ class DebugCounter {
69
82
static unsigned registerCounter (StringRef Name, StringRef Desc) {
70
83
return instance ().addCounter (std::string (Name), std::string (Desc));
71
84
}
85
+ static bool shouldExecuteImpl (unsigned CounterName);
86
+
72
87
inline static bool shouldExecute (unsigned CounterName) {
73
88
if (!isCountingEnabled ())
74
89
return true ;
75
-
76
- auto &Us = instance ();
77
- auto Result = Us.Counters .find (CounterName);
78
- if (Result != Us.Counters .end ()) {
79
- auto &CounterInfo = Result->second ;
80
- ++CounterInfo.Count ;
81
-
82
- // We only execute while the Skip is not smaller than Count,
83
- // and the StopAfter + Skip is larger than Count.
84
- // Negative counters always execute.
85
- if (CounterInfo.Skip < 0 )
86
- return true ;
87
- if (CounterInfo.Skip >= CounterInfo.Count )
88
- return false ;
89
- if (CounterInfo.StopAfter < 0 )
90
- return true ;
91
- return CounterInfo.StopAfter + CounterInfo.Skip >= CounterInfo.Count ;
92
- }
93
- // Didn't find the counter, should we warn?
94
- return true ;
90
+ return shouldExecuteImpl (CounterName);
95
91
}
96
92
97
93
// Return true if a given counter had values set (either programatically or on
@@ -101,18 +97,25 @@ class DebugCounter {
101
97
return instance ().Counters [ID].IsSet ;
102
98
}
103
99
104
- // Return the Count for a counter. This only works for set counters.
105
- static int64_t getCounterValue (unsigned ID) {
100
+ struct CounterState {
101
+ int64_t Count;
102
+ uint64_t ChunkIdx;
103
+ };
104
+
105
+ // Return the state of a counter. This only works for set counters.
106
+ static CounterState getCounterState (unsigned ID) {
106
107
auto &Us = instance ();
107
108
auto Result = Us.Counters .find (ID);
108
109
assert (Result != Us.Counters .end () && " Asking about a non-set counter" );
109
- return Result->second .Count ;
110
+ return { Result->second .Count , Result-> second . CurrChunkIdx } ;
110
111
}
111
112
112
- // Set a registered counter to a given Count value .
113
- static void setCounterValue (unsigned ID, int64_t Count ) {
113
+ // Set a registered counter to a given state .
114
+ static void setCounterState (unsigned ID, CounterState State ) {
114
115
auto &Us = instance ();
115
- Us.Counters [ID].Count = Count;
116
+ auto &Counter = Us.Counters [ID];
117
+ Counter.Count = State.Count ;
118
+ Counter.CurrChunkIdx = State.ChunkIdx ;
116
119
}
117
120
118
121
// Dump or print the current counter set into llvm::dbgs().
@@ -152,11 +155,11 @@ class DebugCounter {
152
155
#ifdef NDEBUG
153
156
return false ;
154
157
#else
155
- return instance ().Enabled ;
158
+ return instance ().Enabled || instance (). ShouldPrintCounter ;
156
159
#endif
157
160
}
158
161
159
- private :
162
+ protected :
160
163
unsigned addCounter (const std::string &Name, const std::string &Desc) {
161
164
unsigned Result = RegisteredCounters.insert (Name);
162
165
Counters[Result] = {};
@@ -166,17 +169,22 @@ class DebugCounter {
166
169
// Struct to store counter info.
167
170
struct CounterInfo {
168
171
int64_t Count = 0 ;
169
- int64_t Skip = 0 ;
170
- int64_t StopAfter = -1 ;
172
+ uint64_t CurrChunkIdx = 0 ;
171
173
bool IsSet = false ;
172
174
std::string Desc;
175
+ SmallVector<Chunk> Chunks;
173
176
};
177
+
174
178
DenseMap<unsigned , CounterInfo> Counters;
175
179
CounterVector RegisteredCounters;
176
180
177
181
// Whether we should do DebugCounting at all. DebugCounters aren't
178
182
// thread-safe, so this should always be false in multithreaded scenarios.
179
183
bool Enabled = false ;
184
+
185
+ bool ShouldPrintCounter = false ;
186
+
187
+ bool BreakOnLast = false ;
180
188
};
181
189
182
190
#define DEBUG_COUNTER (VARNAME, COUNTERNAME, DESC ) \
0 commit comments