/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/include/llvm/Support/DebugCounter.h
Line | Count | Source (jump to first uncovered line) |
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 | | /// \brief 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 | | class DebugCounter { |
57 | | public: |
58 | | /// \brief 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 | 368k | static unsigned registerCounter(StringRef Name, StringRef Desc) { |
70 | 368k | return instance().addCounter(Name, Desc); |
71 | 368k | } |
72 | 224M | inline static bool shouldExecute(unsigned CounterName) { |
73 | 224M | // Compile to nothing when debugging is off |
74 | 224M | #ifdef NDEBUG |
75 | 224M | return true; |
76 | | #else |
77 | | auto &Us = instance(); |
78 | | auto Result = Us.Counters.find(CounterName); |
79 | | if (Result != Us.Counters.end()) { |
80 | | auto &CounterPair = Result->second; |
81 | | // We only execute while the skip (first) is zero and the count (second) |
82 | | // is non-zero. |
83 | | // Negative counters always execute. |
84 | | if (CounterPair.first < 0) |
85 | | return true; |
86 | | if (CounterPair.first != 0) { |
87 | | --CounterPair.first; |
88 | | return false; |
89 | | } |
90 | | if (CounterPair.second < 0) |
91 | | return true; |
92 | | if (CounterPair.second != 0) { |
93 | | --CounterPair.second; |
94 | | return true; |
95 | | } |
96 | | return false; |
97 | | } |
98 | | // Didn't find the counter, should we warn? |
99 | | return true; |
100 | | #endif // NDEBUG |
101 | | } |
102 | | |
103 | | // Return true if a given counter had values set (either programatically or on |
104 | | // the command line). This will return true even if those values are |
105 | | // currently in a state where the counter will always execute. |
106 | 307 | static bool isCounterSet(unsigned ID) { |
107 | 307 | return instance().Counters.count(ID); |
108 | 307 | } |
109 | | |
110 | | // Return the skip and count for a counter. This only works for set counters. |
111 | 0 | static std::pair<int, int> getCounterValue(unsigned ID) { |
112 | 0 | auto &Us = instance(); |
113 | 0 | auto Result = Us.Counters.find(ID); |
114 | 0 | assert(Result != Us.Counters.end() && "Asking about a non-set counter"); |
115 | 0 | return Result->second; |
116 | 0 | } |
117 | | |
118 | | // Set a registered counter to a given value. |
119 | 0 | static void setCounterValue(unsigned ID, const std::pair<int, int> &Val) { |
120 | 0 | auto &Us = instance(); |
121 | 0 | Us.Counters[ID] = Val; |
122 | 0 | } |
123 | | |
124 | | // Dump or print the current counter set into llvm::dbgs(). |
125 | | LLVM_DUMP_METHOD void dump() const; |
126 | | |
127 | | void print(raw_ostream &OS) const; |
128 | | |
129 | | // Get the counter ID for a given named counter, or return 0 if none is found. |
130 | 4 | unsigned getCounterId(const std::string &Name) const { |
131 | 4 | return RegisteredCounters.idFor(Name); |
132 | 4 | } |
133 | | |
134 | | // Return the number of registered counters. |
135 | 0 | unsigned int getNumCounters() const { return RegisteredCounters.size(); } |
136 | | |
137 | | // Return the name and description of the counter with the given ID. |
138 | 4 | std::pair<std::string, std::string> getCounterInfo(unsigned ID) const { |
139 | 4 | return std::make_pair(RegisteredCounters[ID], CounterDesc.lookup(ID)); |
140 | 4 | } |
141 | | |
142 | | // Iterate through the registered counters |
143 | | typedef UniqueVector<std::string> CounterVector; |
144 | 1 | CounterVector::const_iterator begin() const { |
145 | 1 | return RegisteredCounters.begin(); |
146 | 1 | } |
147 | 1 | CounterVector::const_iterator end() const { return RegisteredCounters.end(); } |
148 | | |
149 | | private: |
150 | 368k | unsigned addCounter(const std::string &Name, const std::string &Desc) { |
151 | 368k | unsigned Result = RegisteredCounters.insert(Name); |
152 | 368k | CounterDesc[Result] = Desc; |
153 | 368k | return Result; |
154 | 368k | } |
155 | | DenseMap<unsigned, std::pair<long, long>> Counters; |
156 | | DenseMap<unsigned, std::string> CounterDesc; |
157 | | CounterVector RegisteredCounters; |
158 | | }; |
159 | | |
160 | | #define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC) \ |
161 | | static const unsigned VARNAME = \ |
162 | | DebugCounter::registerCounter(COUNTERNAME, DESC) |
163 | | |
164 | | } // namespace llvm |
165 | | #endif |