Index: include/llvm/ADT/StatisticInfo.h =================================================================== --- /dev/null +++ include/llvm/ADT/StatisticInfo.h @@ -0,0 +1,61 @@ +//===-- llvm/ADT/StatisticInfo.h - Easy way to expose stats -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the 'StatisticInfo' class, which provides access to the +// library of statistics that are collected. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STATISTICINFO_H +#define LLVM_ADT_STATISTICINFO_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/Statistic.h" +#include + +namespace llvm { + +/// This class is used in a ManagedStatic so that it is created on demand (when +/// the first statistic is bumped) and destroyed only when llvm_shutdown is +/// called. We print statistics from the destructor. +/// This class is also used to look up statistic values from applications that +/// use LLVM. +class StatisticInfo { + std::vector Stats; + + friend void llvm::PrintStatistics(); + friend void llvm::PrintStatistics(raw_ostream &OS); + friend void llvm::PrintStatisticsJSON(raw_ostream &OS); + + /// Sort statistics by debugtype,name,description. + void sort(); +public: + using const_iterator = std::vector::const_iterator; + + StatisticInfo(); + ~StatisticInfo(); + + void addStatistic(const Statistic *S) { + Stats.push_back(S); + } + + const_iterator begin() const { return Stats.begin(); } + const_iterator end() const { return Stats.end(); } + iterator_range statistics() const { + return {begin(), end()}; + } +}; + +/// \brief Get the statistics. This can be used to look up the value of +/// statistics without needing to parse JSON. +const iterator_range GetStatistics(); + +} // end namespace llvm + +#endif // LLVM_ADT_STATISTICINFO_H Index: lib/Support/Statistic.cpp =================================================================== --- lib/Support/Statistic.cpp +++ lib/Support/Statistic.cpp @@ -22,6 +22,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StatisticInfo.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" @@ -51,28 +52,6 @@ static bool Enabled; static bool PrintOnExit; -namespace { -/// StatisticInfo - This class is used in a ManagedStatic so that it is created -/// on demand (when the first statistic is bumped) and destroyed only when -/// llvm_shutdown is called. We print statistics from the destructor. -class StatisticInfo { - std::vector Stats; - friend void llvm::PrintStatistics(); - friend void llvm::PrintStatistics(raw_ostream &OS); - friend void llvm::PrintStatisticsJSON(raw_ostream &OS); - - /// Sort statistics by debugtype,name,description. - void sort(); -public: - StatisticInfo(); - ~StatisticInfo(); - - void addStatistic(const Statistic *S) { - Stats.push_back(S); - } -}; -} - static ManagedStatic StatInfo; static ManagedStatic > StatLock; @@ -205,3 +184,7 @@ } #endif } + +const iterator_range llvm::GetStatistics() { + return StatInfo->statistics(); +} Index: unittests/ADT/CMakeLists.txt =================================================================== --- unittests/ADT/CMakeLists.txt +++ unittests/ADT/CMakeLists.txt @@ -56,6 +56,7 @@ SparseBitVectorTest.cpp SparseMultiSetTest.cpp SparseSetTest.cpp + StatisticTest.cpp StringExtrasTest.cpp StringMapTest.cpp StringRefTest.cpp Index: unittests/ADT/StatisticTest.cpp =================================================================== --- /dev/null +++ unittests/ADT/StatisticTest.cpp @@ -0,0 +1,108 @@ +//===- llvm/unittest/ADT/StatisticTest.cpp - Statistic unit tests ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StatisticInfo.h" +#include "llvm/Support/raw_ostream.h" +#include "gtest/gtest.h" +using namespace llvm; + +namespace { +#define DEBUG_TYPE "unittest" +STATISTIC(Counter, "Counts things"); +STATISTIC(Counter2, "Counts other things"); + +TEST(StatisticTest, Count) { + EnableStatistics(); + + Counter = 0; + EXPECT_EQ(Counter, 0u); + Counter++; + Counter++; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) + EXPECT_EQ(Counter, 2u); +#else + EXPECT_EQ(Counter, 0u); +#endif +} + +TEST(StatisticTest, Assign) { + EnableStatistics(); + + Counter = 2; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) + EXPECT_EQ(Counter, 2u); +#else + EXPECT_EQ(Counter, 0u); +#endif +} + +TEST(StatisticTest, API) { + EnableStatistics(); + + Counter = 0; + EXPECT_EQ(Counter, 0u); + Counter++; + Counter++; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) + EXPECT_EQ(Counter, 2u); +#else + EXPECT_EQ(Counter, 0u); +#endif + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) + const auto Range1 = GetStatistics(); + EXPECT_NE(Range1.begin(), Range1.end()); + EXPECT_EQ(Range1.begin() + 1, Range1.end()); + + const Statistic *S1 = nullptr; + const Statistic *S2 = nullptr; + for (const auto *S : Range1) { + if (std::string(S->getName()) == "Counter") + S1 = S; + if (std::string(S->getName()) == "Counter2") + S2 = S; + } + + EXPECT_NE(S1, nullptr); + EXPECT_EQ(S2, nullptr); + + // Counter2 will be registered when it's first touched. + Counter2++; + + const auto Range2 = GetStatistics(); + EXPECT_NE(Range2.begin(), Range2.end()); + EXPECT_EQ(Range2.begin() + 2, Range2.end()); + + S1 = nullptr; + for (const auto *S : Range2) { + if (std::string(S->getName()) == "Counter") + S1 = S; + if (std::string(S->getName()) == "Counter2") + S2 = S; + } + + EXPECT_NE(S1, nullptr); + EXPECT_NE(S2, nullptr); + + EXPECT_EQ(S1->getName(), "Counter"); + EXPECT_EQ(S1->getDesc(), "Counts things"); + EXPECT_EQ(S1->getValue(), 2u); + + EXPECT_EQ(S2->getName(), "Counter2"); + EXPECT_EQ(S2->getDesc(), "Counts other things"); + EXPECT_EQ(S2->getValue(), 1u); +#else + Counter2++; + auto &Range = GetStatistics(); + EXPECT_EQ(Range.begin(), Range.end()); +#endif +} + +} // end anonymous namespace