summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/cmake/modules/HandleLLVMOptions.cmake4
-rw-r--r--llvm/include/llvm/ADT/Statistic.h16
-rw-r--r--llvm/include/llvm/Config/llvm-config.h.cmake5
-rw-r--r--llvm/lib/Support/Statistic.cpp30
-rw-r--r--llvm/unittests/ADT/CMakeLists.txt1
-rw-r--r--llvm/unittests/ADT/StatisticTest.cpp106
6 files changed, 155 insertions, 7 deletions
diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake
index 2dc5690355c..f508db2040c 100644
--- a/llvm/cmake/modules/HandleLLVMOptions.cmake
+++ b/llvm/cmake/modules/HandleLLVMOptions.cmake
@@ -881,3 +881,7 @@ function(get_compile_definitions)
set(LLVM_DEFINITIONS "${result}" PARENT_SCOPE)
endfunction()
get_compile_definitions()
+
+# The default for LLVM_ENABLE_STATS depends on whether NDEBUG is defined or not.
+# LLVM_ENABLE_ASSERTIONS controls that so re-use it as the default.
+option(LLVM_ENABLE_STATS "Enable statistics collection" ${LLVM_ENABLE_ASSERTIONS})
diff --git a/llvm/include/llvm/ADT/Statistic.h b/llvm/include/llvm/ADT/Statistic.h
index 6d478b14015..71d7db846e9 100644
--- a/llvm/include/llvm/ADT/Statistic.h
+++ b/llvm/include/llvm/ADT/Statistic.h
@@ -26,14 +26,17 @@
#ifndef LLVM_ADT_STATISTIC_H
#define LLVM_ADT_STATISTIC_H
+#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Compiler.h"
#include <atomic>
#include <memory>
+#include <vector>
namespace llvm {
class raw_ostream;
class raw_fd_ostream;
+class StringRef;
class Statistic {
public:
@@ -60,7 +63,7 @@ public:
// Allow use of this class as the value itself.
operator unsigned() const { return getValue(); }
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
+#if LLVM_ENABLE_STATS
const Statistic &operator=(unsigned Val) {
Value.store(Val, std::memory_order_relaxed);
return init();
@@ -142,7 +145,7 @@ public:
void updateMax(unsigned V) {}
-#endif // !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
+#endif // LLVM_ENABLE_STATS
protected:
Statistic &init() {
@@ -180,6 +183,15 @@ void PrintStatistics(raw_ostream &OS);
/// PrintStatisticsJSON().
void PrintStatisticsJSON(raw_ostream &OS);
+/// \brief Get the statistics. This can be used to look up the value of
+/// statistics without needing to parse JSON.
+///
+/// This function does not prevent statistics being updated by other threads
+/// during it's execution. It will return the value at the point that it is
+/// read. However, it will prevent new statistics from registering until it
+/// completes.
+const std::vector<std::pair<StringRef, unsigned>> GetStatistics();
+
} // end namespace llvm
#endif // LLVM_ADT_STATISTIC_H
diff --git a/llvm/include/llvm/Config/llvm-config.h.cmake b/llvm/include/llvm/Config/llvm-config.h.cmake
index 4daa00f3bc4..6b1cb0b0d30 100644
--- a/llvm/include/llvm/Config/llvm-config.h.cmake
+++ b/llvm/include/llvm/Config/llvm-config.h.cmake
@@ -77,4 +77,9 @@
/* LLVM version string */
#define LLVM_VERSION_STRING "${PACKAGE_VERSION}"
+/* Whether LLVM records statistics for use with GetStatistics(),
+ * PrintStatistics() or PrintStatisticsJSON()
+ */
+#cmakedefine01 LLVM_ENABLE_STATS
+
#endif
diff --git a/llvm/lib/Support/Statistic.cpp b/llvm/lib/Support/Statistic.cpp
index 370274dc299..67b07162b9a 100644
--- a/llvm/lib/Support/Statistic.cpp
+++ b/llvm/lib/Support/Statistic.cpp
@@ -52,11 +52,14 @@ 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.
+/// 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<const Statistic*> Stats;
+
friend void llvm::PrintStatistics();
friend void llvm::PrintStatistics(raw_ostream &OS);
friend void llvm::PrintStatisticsJSON(raw_ostream &OS);
@@ -64,14 +67,22 @@ class StatisticInfo {
/// Sort statistics by debugtype,name,description.
void sort();
public:
+ using const_iterator = std::vector<const Statistic *>::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<const_iterator> statistics() const {
+ return {begin(), end()};
+ }
};
-}
+} // end anonymous namespace
static ManagedStatic<StatisticInfo> StatInfo;
static ManagedStatic<sys::SmartMutex<true> > StatLock;
@@ -180,7 +191,7 @@ void llvm::PrintStatisticsJSON(raw_ostream &OS) {
}
void llvm::PrintStatistics() {
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
+#if LLVM_ENABLE_STATS
StatisticInfo &Stats = *StatInfo;
// Statistics not enabled?
@@ -205,3 +216,12 @@ void llvm::PrintStatistics() {
}
#endif
}
+
+const std::vector<std::pair<StringRef, unsigned>> llvm::GetStatistics() {
+ sys::SmartScopedLock<true> Reader(*StatLock);
+ std::vector<std::pair<StringRef, unsigned>> ReturnStats;
+
+ for (const auto &Stat : StatInfo->statistics())
+ ReturnStats.emplace_back(Stat->getName(), Stat->getValue());
+ return ReturnStats;
+}
diff --git a/llvm/unittests/ADT/CMakeLists.txt b/llvm/unittests/ADT/CMakeLists.txt
index c0d511000f6..d11bdc7a6b2 100644
--- a/llvm/unittests/ADT/CMakeLists.txt
+++ b/llvm/unittests/ADT/CMakeLists.txt
@@ -56,6 +56,7 @@ set(ADTSources
SparseBitVectorTest.cpp
SparseMultiSetTest.cpp
SparseSetTest.cpp
+ StatisticTest.cpp
StringExtrasTest.cpp
StringMapTest.cpp
StringRefTest.cpp
diff --git a/llvm/unittests/ADT/StatisticTest.cpp b/llvm/unittests/ADT/StatisticTest.cpp
new file mode 100644
index 00000000000..3ddfe56cc8f
--- /dev/null
+++ b/llvm/unittests/ADT/StatisticTest.cpp
@@ -0,0 +1,106 @@
+//===- 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/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 LLVM_ENABLE_STATS
+ EXPECT_EQ(Counter, 2u);
+#else
+ EXPECT_EQ(Counter, 0u);
+#endif
+}
+
+TEST(StatisticTest, Assign) {
+ EnableStatistics();
+
+ Counter = 2;
+#if 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 LLVM_ENABLE_STATS
+ EXPECT_EQ(Counter, 2u);
+#else
+ EXPECT_EQ(Counter, 0u);
+#endif
+
+#if LLVM_ENABLE_STATS
+ const auto Range1 = GetStatistics();
+ EXPECT_NE(Range1.begin(), Range1.end());
+ EXPECT_EQ(Range1.begin() + 1, Range1.end());
+
+ Optional<std::pair<StringRef, unsigned>> S1;
+ Optional<std::pair<StringRef, unsigned>> S2;
+ for (const auto &S : Range1) {
+ if (std::string(S.first) == "Counter")
+ S1 = S;
+ if (std::string(S.first) == "Counter2")
+ S2 = S;
+ }
+
+ EXPECT_NE(S1.hasValue(), false);
+ EXPECT_EQ(S2.hasValue(), false);
+
+ // 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 = None;
+ S2 = None;
+ for (const auto &S : Range2) {
+ if (std::string(S.first) == "Counter")
+ S1 = S;
+ if (std::string(S.first) == "Counter2")
+ S2 = S;
+ }
+
+ EXPECT_NE(S1.hasValue(), false);
+ EXPECT_NE(S2.hasValue(), false);
+
+ EXPECT_EQ(S1->first, "Counter");
+ EXPECT_EQ(S1->second, 2u);
+
+ EXPECT_EQ(S2->first, "Counter2");
+ EXPECT_EQ(S2->second, 1u);
+#else
+ Counter2++;
+ auto &Range = GetStatistics();
+ EXPECT_EQ(Range.begin(), Range.end());
+#endif
+}
+
+} // end anonymous namespace
OpenPOWER on IntegriCloud