Skip to content

Commit bc95377

Browse files
committed
[DebugCounter] Add support for non-continous ranges.
+ Script for bisecting though a build
1 parent adc11b3 commit bc95377

22 files changed

+577
-124
lines changed

llvm/docs/ProgrammersManual.rst

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,16 +1362,14 @@ Whatever code you want that control, use ``DebugCounter::shouldExecute`` to cont
13621362
if (DebugCounter::shouldExecute(DeleteAnInstruction))
13631363
I->eraseFromParent();
13641364

1365-
That's all you have to do. Now, using opt, you can control when this code triggers using
1366-
the '``--debug-counter``' option. There are two counters provided, ``skip`` and ``count``.
1367-
``skip`` is the number of times to skip execution of the codepath. ``count`` is the number
1368-
of times, once we are done skipping, to execute the codepath.
1365+
That's all you have to do. Now, using opt, you can control when this code triggers using
1366+
the '``--debug-counter``' Options.To specify when to execute the codepath.
13691367

13701368
.. code-block:: none
13711369
1372-
$ opt --debug-counter=passname-delete-instruction-skip=1,passname-delete-instruction-count=2 -passname
1370+
$ opt --debug-counter=passname-delete-instruction=2-3 -passname
13731371
1374-
This will skip the above code the first time we hit it, then execute it twice, then skip the rest of the executions.
1372+
This will skip the above code the first two times we hit it, then execute it 2 times, then skip the rest of the executions.
13751373

13761374
So if executed on the following code:
13771375

@@ -1385,8 +1383,32 @@ So if executed on the following code:
13851383
It would delete number ``%2`` and ``%3``.
13861384

13871385
A utility is provided in `utils/bisect-skip-count` to binary search
1388-
skip and count arguments. It can be used to automatically minimize the
1389-
skip and count for a debug-counter variable.
1386+
the begin and end of the range argument. It can be used to automatically minimize the
1387+
range for a debug-counter variable.
1388+
1389+
A more general utility is provided in `llvm/tools/delta-driver/delta-driver.cpp` to drive the automated delta debugging.
1390+
1391+
How to use delta-driver:
1392+
First, Figure out the number of calls to the debug counter you want to minimize.
1393+
To do so, run the compilation command causing you want to minimize with `-print-debug-counter` adding a `-mllvm` if needed.
1394+
Than find the line with the counter of interest. it should look like:
1395+
.. code-block:: none
1396+
1397+
my-counter : {5678,empty}
1398+
1399+
The number of calls to `my-counter` is 5678
1400+
1401+
Than Find the minimum set of chunks that is interesting, with `delta-driver`.
1402+
Build a reproducer script like:
1403+
.. code-block:: bash
1404+
1405+
#! /bin/bash
1406+
opt -debug-counter=my-counter=$1
1407+
# ... Test result of the command. Failure of the script is considered interesting
1408+
1409+
Than run `delta-driver my-script.sh 0-5678 2>&1 | tee dump_bisect`
1410+
This command may take some time.
1411+
but when it is done, it will print the result like: `Minimal Chunks = 0:1:5:11-12:33-34`
13901412

13911413
.. _ViewGraph:
13921414

llvm/include/llvm/IR/PassManager.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ extern llvm::cl::opt<bool> UseNewDbgInfoFormat;
6464

6565
namespace llvm {
6666

67+
// Used for debug counter of adding a pass to the pipeline
68+
bool shouldAddNewPMPass();
69+
6770
// Forward declare the analysis manager template.
6871
template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager;
6972

@@ -247,6 +250,8 @@ class PassManager : public PassInfoMixin<
247250

248251
// FIXME: Revert to enable_if style when gcc >= 11.1
249252
template <typename PassT> LLVM_ATTRIBUTE_MINSIZE void addPass(PassT &&Pass) {
253+
if (!shouldAddNewPMPass())
254+
return;
250255
using PassModelT =
251256
detail::PassModel<IRUnitT, PassT, AnalysisManagerT, ExtraArgTs...>;
252257
if constexpr (!std::is_same_v<PassT, PassManager>) {

llvm/include/llvm/Support/DebugCounter.h

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#ifndef LLVM_SUPPORT_DEBUGCOUNTER_H
4444
#define LLVM_SUPPORT_DEBUGCOUNTER_H
4545

46+
#include "llvm/ADT/ArrayRef.h"
4647
#include "llvm/ADT/DenseMap.h"
4748
#include "llvm/ADT/StringRef.h"
4849
#include "llvm/ADT/UniqueVector.h"
@@ -55,6 +56,19 @@ class raw_ostream;
5556

5657
class DebugCounter {
5758
public:
59+
struct Chunk {
60+
int64_t Begin;
61+
int64_t End;
62+
void print(llvm::raw_ostream &OS);
63+
bool contains(int64_t Idx) { return Idx >= Begin && Idx <= End; }
64+
};
65+
66+
static void printChunks(raw_ostream &OS, ArrayRef<Chunk>);
67+
68+
/// Return true on parsing error and print the error message on the
69+
/// llvm::errs()
70+
static bool parseChunks(StringRef Str, SmallVector<Chunk> &Res);
71+
5872
/// Returns a reference to the singleton instance.
5973
static DebugCounter &instance();
6074

@@ -69,29 +83,12 @@ class DebugCounter {
6983
static unsigned registerCounter(StringRef Name, StringRef Desc) {
7084
return instance().addCounter(std::string(Name), std::string(Desc));
7185
}
86+
static bool shouldExecuteImpl(unsigned CounterName);
87+
7288
inline static bool shouldExecute(unsigned CounterName) {
7389
if (!isCountingEnabled())
7490
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;
91+
return shouldExecuteImpl(CounterName);
9592
}
9693

9794
// Return true if a given counter had values set (either programatically or on
@@ -101,18 +98,25 @@ class DebugCounter {
10198
return instance().Counters[ID].IsSet;
10299
}
103100

104-
// Return the Count for a counter. This only works for set counters.
105-
static int64_t getCounterValue(unsigned ID) {
101+
struct CounterState {
102+
int64_t Count;
103+
uint64_t ChunkIdx;
104+
};
105+
106+
// Return the state of a counter. This only works for set counters.
107+
static CounterState getCounterState(unsigned ID) {
106108
auto &Us = instance();
107109
auto Result = Us.Counters.find(ID);
108110
assert(Result != Us.Counters.end() && "Asking about a non-set counter");
109-
return Result->second.Count;
111+
return {Result->second.Count, Result->second.CurrChunkIdx};
110112
}
111113

112-
// Set a registered counter to a given Count value.
113-
static void setCounterValue(unsigned ID, int64_t Count) {
114+
// Set a registered counter to a given state.
115+
static void setCounterState(unsigned ID, CounterState State) {
114116
auto &Us = instance();
115-
Us.Counters[ID].Count = Count;
117+
auto &Counter = Us.Counters[ID];
118+
Counter.Count = State.Count;
119+
Counter.CurrChunkIdx = State.ChunkIdx;
116120
}
117121

118122
// Dump or print the current counter set into llvm::dbgs().
@@ -152,11 +156,11 @@ class DebugCounter {
152156
#ifdef NDEBUG
153157
return false;
154158
#else
155-
return instance().Enabled;
159+
return instance().Enabled || instance().ShouldPrintCounter;
156160
#endif
157161
}
158162

159-
private:
163+
protected:
160164
unsigned addCounter(const std::string &Name, const std::string &Desc) {
161165
unsigned Result = RegisteredCounters.insert(Name);
162166
Counters[Result] = {};
@@ -166,17 +170,22 @@ class DebugCounter {
166170
// Struct to store counter info.
167171
struct CounterInfo {
168172
int64_t Count = 0;
169-
int64_t Skip = 0;
170-
int64_t StopAfter = -1;
173+
uint64_t CurrChunkIdx = 0;
171174
bool IsSet = false;
172175
std::string Desc;
176+
SmallVector<Chunk> Chunks;
173177
};
178+
174179
DenseMap<unsigned, CounterInfo> Counters;
175180
CounterVector RegisteredCounters;
176181

177182
// Whether we should do DebugCounting at all. DebugCounters aren't
178183
// thread-safe, so this should always be false in multithreaded scenarios.
179184
bool Enabled = false;
185+
186+
bool ShouldPrintCounter = false;
187+
188+
bool BreakOnLast = false;
180189
};
181190

182191
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC) \

llvm/lib/IR/PassManager.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,20 @@
88

99
#include "llvm/IR/PassManager.h"
1010
#include "llvm/IR/PassManagerImpl.h"
11+
#include "llvm/Support/DebugCounter.h"
1112
#include <optional>
1213

1314
using namespace llvm;
1415

1516
namespace llvm {
17+
18+
DEBUG_COUNTER(AddNewPMPassCounter, "new-pm-pass-counter",
19+
"Control what passes get run");
20+
21+
bool shouldAddNewPMPass() {
22+
return DebugCounter::shouldExecute(AddNewPMPassCounter);
23+
}
24+
1625
// Explicit template instantiations and specialization defininitions for core
1726
// template typedefs.
1827
template class AllAnalysesOn<Module>;

0 commit comments

Comments
 (0)