Line data Source code
1 : //===- llvm/Support/DebugCounter.h - Debug counter support ------*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : /// \file
10 : /// This file provides an implementation of debug counters. Debug
11 : /// counters are a tool that let you narrow down a miscompilation to a specific
12 : /// thing happening.
13 : ///
14 : /// To give a use case: Imagine you have a file, very large, and you
15 : /// are trying to understand the minimal transformation that breaks it. Bugpoint
16 : /// and bisection is often helpful here in narrowing it down to a specific pass,
17 : /// but it's still a very large file, and a very complicated pass to try to
18 : /// debug. That is where debug counting steps in. You can instrument the pass
19 : /// with a debug counter before it does a certain thing, and depending on the
20 : /// counts, it will either execute that thing or not. The debug counter itself
21 : /// consists of a skip and a count. Skip is the number of times shouldExecute
22 : /// needs to be called before it returns true. Count is the number of times to
23 : /// return true once Skip is 0. So a skip=47, count=2 ,would skip the first 47
24 : /// executions by returning false from shouldExecute, then execute twice, and
25 : /// then return false again.
26 : /// Note that a counter set to a negative number will always execute.
27 : /// For a concrete example, during predicateinfo creation, the renaming pass
28 : /// replaces each use with a renamed use.
29 : ////
30 : /// If I use DEBUG_COUNTER to create a counter called "predicateinfo", and
31 : /// variable name RenameCounter, and then instrument this renaming with a debug
32 : /// counter, like so:
33 : ///
34 : /// if (!DebugCounter::shouldExecute(RenameCounter)
35 : /// <continue or return or whatever not executing looks like>
36 : ///
37 : /// Now I can, from the command line, make it rename or not rename certain uses
38 : /// by setting the skip and count.
39 : /// So for example
40 : /// bin/opt -debug-counter=predicateinfo-skip=47,predicateinfo-count=1
41 : /// will skip renaming the first 47 uses, then rename one, then skip the rest.
42 : //===----------------------------------------------------------------------===//
43 :
44 : #ifndef LLVM_SUPPORT_DEBUGCOUNTER_H
45 : #define LLVM_SUPPORT_DEBUGCOUNTER_H
46 :
47 : #include "llvm/ADT/DenseMap.h"
48 : #include "llvm/ADT/UniqueVector.h"
49 : #include "llvm/Support/CommandLine.h"
50 : #include "llvm/Support/Debug.h"
51 : #include "llvm/Support/raw_ostream.h"
52 : #include <string>
53 :
54 : namespace llvm {
55 :
56 113936 : class DebugCounter {
57 : public:
58 : /// Returns a reference to the singleton instance.
59 : static DebugCounter &instance();
60 :
61 : // Used by the command line option parser to push a new value it parsed.
62 : void push_back(const std::string &);
63 :
64 : // Register a counter with the specified name.
65 : //
66 : // FIXME: Currently, counter registration is required to happen before command
67 : // line option parsing. The main reason to register counters is to produce a
68 : // nice list of them on the command line, but i'm not sure this is worth it.
69 1481168 : static unsigned registerCounter(StringRef Name, StringRef Desc) {
70 4443504 : return instance().addCounter(Name, Desc);
71 : }
72 : inline static bool shouldExecute(unsigned CounterName) {
73 : if (!isCountingEnabled())
74 : 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;
95 : }
96 :
97 : // Return true if a given counter had values set (either programatically or on
98 : // the command line). This will return true even if those values are
99 : // currently in a state where the counter will always execute.
100 : static bool isCounterSet(unsigned ID) {
101 325 : return instance().Counters[ID].IsSet;
102 : }
103 :
104 : // Return the Count for a counter. This only works for set counters.
105 0 : static int64_t getCounterValue(unsigned ID) {
106 0 : auto &Us = instance();
107 0 : auto Result = Us.Counters.find(ID);
108 : assert(Result != Us.Counters.end() && "Asking about a non-set counter");
109 0 : return Result->second.Count;
110 : }
111 :
112 : // Set a registered counter to a given Count value.
113 : static void setCounterValue(unsigned ID, int64_t Count) {
114 : auto &Us = instance();
115 : Us.Counters[ID].Count = Count;
116 : }
117 :
118 : // Dump or print the current counter set into llvm::dbgs().
119 : LLVM_DUMP_METHOD void dump() const;
120 :
121 : void print(raw_ostream &OS) const;
122 :
123 : // Get the counter ID for a given named counter, or return 0 if none is found.
124 : unsigned getCounterId(const std::string &Name) const {
125 : return RegisteredCounters.idFor(Name);
126 : }
127 :
128 : // Return the number of registered counters.
129 : unsigned int getNumCounters() const { return RegisteredCounters.size(); }
130 :
131 : // Return the name and description of the counter with the given ID.
132 13 : std::pair<std::string, std::string> getCounterInfo(unsigned ID) const {
133 13 : return std::make_pair(RegisteredCounters[ID], Counters.lookup(ID).Desc);
134 : }
135 :
136 : // Iterate through the registered counters
137 : typedef UniqueVector<std::string> CounterVector;
138 : CounterVector::const_iterator begin() const {
139 : return RegisteredCounters.begin();
140 : }
141 : CounterVector::const_iterator end() const { return RegisteredCounters.end(); }
142 :
143 : // Force-enables counting all DebugCounters.
144 : //
145 : // Since DebugCounters are incompatible with threading (not only do they not
146 : // make sense, but we'll also see data races), this should only be used in
147 : // contexts where we're certain we won't spawn threads.
148 0 : static void enableAllCounters() { instance().Enabled = true; }
149 :
150 : private:
151 : static bool isCountingEnabled() {
152 : // Compile to nothing when debugging is off
153 : #ifdef NDEBUG
154 : return false;
155 : #else
156 : return instance().Enabled;
157 : #endif
158 : }
159 :
160 1481168 : unsigned addCounter(const std::string &Name, const std::string &Desc) {
161 1481168 : unsigned Result = RegisteredCounters.insert(Name);
162 2962336 : Counters[Result] = {};
163 1481168 : Counters[Result].Desc = Desc;
164 1481168 : return Result;
165 : }
166 : // Struct to store counter info.
167 2830295 : struct CounterInfo {
168 : int64_t Count = 0;
169 : int64_t Skip = 0;
170 : int64_t StopAfter = -1;
171 : bool IsSet = false;
172 : std::string Desc;
173 : };
174 : DenseMap<unsigned, CounterInfo> Counters;
175 : CounterVector RegisteredCounters;
176 :
177 : // Whether we should do DebugCounting at all. DebugCounters aren't
178 : // thread-safe, so this should always be false in multithreaded scenarios.
179 : bool Enabled = false;
180 : };
181 :
182 : #define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC) \
183 : static const unsigned VARNAME = \
184 : DebugCounter::registerCounter(COUNTERNAME, DESC)
185 :
186 : } // namespace llvm
187 : #endif
|