LCOV - code coverage report
Current view: top level - include/llvm/Support - DebugCounter.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 14 18 77.8 %
Date: 2017-09-14 15:23:50 Functions: 6 7 85.7 %
Legend: Lines: hit not hit

          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             : /// \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      537588 : 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      289224 :   static unsigned registerCounter(StringRef Name, StringRef Desc) {
      70     1446120 :     return instance().addCounter(Name, Desc);
      71             :   }
      72             :   inline static bool shouldExecute(unsigned CounterName) {
      73             : // Compile to nothing when debugging is off
      74             : #ifdef NDEBUG
      75             :     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         614 :     return instance().Counters.count(ID);
     108             :   }
     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             :     assert(Result != Us.Counters.end() && "Asking about a non-set counter");
     115           0 :     return Result->second;
     116             :   }
     117             : 
     118             :   // Set a registered counter to a given value.
     119             :   static void setCounterValue(unsigned ID, const std::pair<int, int> &Val) {
     120             :     auto &Us = instance();
     121             :     Us.Counters[ID] = Val;
     122             :   }
     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             :   unsigned getCounterId(const std::string &Name) const {
     131         184 :     return RegisteredCounters.idFor(Name);
     132             :   }
     133             : 
     134             :   // Return the number of registered counters.
     135             :   unsigned int getNumCounters() const { return RegisteredCounters.size(); }
     136             : 
     137             :   // Return the name and description of the counter with the given ID.
     138          92 :   std::pair<std::string, std::string> getCounterInfo(unsigned ID) const {
     139         368 :     return std::make_pair(RegisteredCounters[ID], CounterDesc.lookup(ID));
     140             :   }
     141             : 
     142             :   // Iterate through the registered counters
     143             :   typedef UniqueVector<std::string> CounterVector;
     144             :   CounterVector::const_iterator begin() const {
     145          46 :     return RegisteredCounters.begin();
     146             :   }
     147          46 :   CounterVector::const_iterator end() const { return RegisteredCounters.end(); }
     148             : 
     149             : private:
     150      289224 :   unsigned addCounter(const std::string &Name, const std::string &Desc) {
     151      289224 :     unsigned Result = RegisteredCounters.insert(Name);
     152      867672 :     CounterDesc[Result] = Desc;
     153      289224 :     return Result;
     154             :   }
     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

Generated by: LCOV version 1.13