LCOV - code coverage report
Current view: top level - include/llvm/Support - DebugCounter.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 12 17 70.6 %
Date: 2018-10-20 13:21:21 Functions: 3 4 75.0 %
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             : /// 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

Generated by: LCOV version 1.13