1717// / debug. That is where debug counting steps in. You can instrument the pass
1818// / with a debug counter before it does a certain thing, and depending on the
1919// / 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.
2827// //
2928// / If I use DEBUG_COUNTER to create a counter called "predicateinfo", and
3029// / variable name RenameCounter, and then instrument this renaming with a debug
3433// / <continue or return or whatever not executing looks like>
3534// /
3635// / 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 .
3837// / So for example
39- // / bin/opt -debug-counter=predicateinfo-skip =47,predicateinfo-count=1
38+ // / bin/opt -debug-counter=predicateinfo=47
4039// / will skip renaming the first 47 uses, then rename one, then skip the rest.
4140// ===----------------------------------------------------------------------===//
4241
4342#ifndef LLVM_SUPPORT_DEBUGCOUNTER_H
4443#define LLVM_SUPPORT_DEBUGCOUNTER_H
4544
45+ #include " llvm/ADT/ArrayRef.h"
4646#include " llvm/ADT/DenseMap.h"
4747#include " llvm/ADT/StringRef.h"
4848#include " llvm/ADT/UniqueVector.h"
@@ -55,6 +55,19 @@ class raw_ostream;
5555
5656class DebugCounter {
5757public:
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+
5871 // / Returns a reference to the singleton instance.
5972 static DebugCounter &instance ();
6073
@@ -69,29 +82,12 @@ class DebugCounter {
6982 static unsigned registerCounter (StringRef Name, StringRef Desc) {
7083 return instance ().addCounter (std::string (Name), std::string (Desc));
7184 }
85+ static bool shouldExecuteImpl (unsigned CounterName);
86+
7287 inline static bool shouldExecute (unsigned CounterName) {
7388 if (!isCountingEnabled ())
7489 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);
9591 }
9692
9793 // Return true if a given counter had values set (either programatically or on
@@ -101,18 +97,25 @@ class DebugCounter {
10197 return instance ().Counters [ID].IsSet ;
10298 }
10399
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) {
106107 auto &Us = instance ();
107108 auto Result = Us.Counters .find (ID);
108109 assert (Result != Us.Counters .end () && " Asking about a non-set counter" );
109- return Result->second .Count ;
110+ return { Result->second .Count , Result-> second . CurrChunkIdx } ;
110111 }
111112
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 ) {
114115 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 ;
116119 }
117120
118121 // Dump or print the current counter set into llvm::dbgs().
@@ -152,11 +155,11 @@ class DebugCounter {
152155#ifdef NDEBUG
153156 return false ;
154157#else
155- return instance ().Enabled ;
158+ return instance ().Enabled || instance (). ShouldPrintCounter ;
156159#endif
157160 }
158161
159- private :
162+ protected :
160163 unsigned addCounter (const std::string &Name, const std::string &Desc) {
161164 unsigned Result = RegisteredCounters.insert (Name);
162165 Counters[Result] = {};
@@ -166,17 +169,22 @@ class DebugCounter {
166169 // Struct to store counter info.
167170 struct CounterInfo {
168171 int64_t Count = 0 ;
169- int64_t Skip = 0 ;
170- int64_t StopAfter = -1 ;
172+ uint64_t CurrChunkIdx = 0 ;
171173 bool IsSet = false ;
172174 std::string Desc;
175+ SmallVector<Chunk> Chunks;
173176 };
177+
174178 DenseMap<unsigned , CounterInfo> Counters;
175179 CounterVector RegisteredCounters;
176180
177181 // Whether we should do DebugCounting at all. DebugCounters aren't
178182 // thread-safe, so this should always be false in multithreaded scenarios.
179183 bool Enabled = false ;
184+
185+ bool ShouldPrintCounter = false ;
186+
187+ bool BreakOnLast = false ;
180188};
181189
182190#define DEBUG_COUNTER (VARNAME, COUNTERNAME, DESC ) \
0 commit comments