From 7ae684a8b48aee6bb67f1acd3221b458fb7cea05 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Thu, 2 Jun 2016 08:44:05 +0000 Subject: [PATCH] Switch statistics to use relaxed updates to a std::atomic. This removes usage of the hacky, incorrect, and TSan-unfriendly home-grown atomics. It should actually be more efficient in some cases. Based on our existing usage of , all of this is portably available AFAICT. One small challenge is initializing the stastic, but I've tried a comparable sample out on MSVC (the most likely to complain here) and it seems to work. Will have to watch the build bots of course. llvm-svn: 271504 --- llvm/include/llvm/ADT/Statistic.h | 43 ++++++++++++++----------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/llvm/include/llvm/ADT/Statistic.h b/llvm/include/llvm/ADT/Statistic.h index 320e5c12259b..661fea72cf0e 100644 --- a/llvm/include/llvm/ADT/Statistic.h +++ b/llvm/include/llvm/ADT/Statistic.h @@ -28,6 +28,7 @@ #include "llvm/Support/Atomic.h" #include "llvm/Support/Compiler.h" +#include #include namespace llvm { @@ -38,10 +39,10 @@ class Statistic { public: const char *Name; const char *Desc; - volatile llvm::sys::cas_flag Value; + std::atomic Value; bool Initialized; - llvm::sys::cas_flag getValue() const { return Value; } + unsigned getValue() const { return Value.load(std::memory_order_relaxed); } const char *getName() const { return Name; } const char *getDesc() const { return Desc; } @@ -52,51 +53,45 @@ public: } // Allow use of this class as the value itself. - operator unsigned() const { return Value; } + operator unsigned() const { return getValue(); } #if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) const Statistic &operator=(unsigned Val) { - Value = Val; + Value.store(Val, std::memory_order_relaxed); return init(); } const Statistic &operator++() { - // FIXME: This function and all those that follow carefully use an - // atomic operation to update the value safely in the presence of - // concurrent accesses, but not to read the return value, so the - // return value is not thread safe. - sys::AtomicIncrement(&Value); + Value.fetch_add(1, std::memory_order_relaxed); return init(); } unsigned operator++(int) { init(); - unsigned OldValue = Value; - sys::AtomicIncrement(&Value); - return OldValue; + return Value.fetch_add(1, std::memory_order_relaxed); } const Statistic &operator--() { - sys::AtomicDecrement(&Value); + Value.fetch_sub(1, std::memory_order_relaxed); return init(); } unsigned operator--(int) { init(); - unsigned OldValue = Value; - sys::AtomicDecrement(&Value); - return OldValue; + return Value.fetch_sub(1, std::memory_order_relaxed); } - const Statistic &operator+=(const unsigned &V) { - if (!V) return *this; - sys::AtomicAdd(&Value, V); + const Statistic &operator+=(unsigned V) { + if (V == 0) + return *this; + Value.fetch_add(V, std::memory_order_relaxed); return init(); } - const Statistic &operator-=(const unsigned &V) { - if (!V) return *this; - sys::AtomicAdd(&Value, -V); + const Statistic &operator-=(unsigned V) { + if (V == 0) + return *this; + Value.fetch_sub(V, std::memory_order_relaxed); return init(); } @@ -145,8 +140,8 @@ protected: // STATISTIC - A macro to make definition of statistics really simple. This // automatically passes the DEBUG_TYPE of the file into the statistic. -#define STATISTIC(VARNAME, DESC) \ - static llvm::Statistic VARNAME = { DEBUG_TYPE, DESC, 0, 0 } +#define STATISTIC(VARNAME, DESC) \ + static llvm::Statistic VARNAME = {DEBUG_TYPE, DESC, {0}, 0} /// \brief Enable the collection and printing of statistics. void EnableStatistics();