Commit f682f7e9 by Eric Committed by GitHub

Implement ClobberMemory() and fix DoNotOptimize on MSVC. (#352)

I recently learned Windows provides a function called _ReadWriteBarrier which is literally ClobberMemory under a different name. This patch uses it to implement ClobberMemory under MSVC.
parent 8ae6448c
...@@ -365,7 +365,7 @@ static void BM_vector_push_back(benchmark::State& state) { ...@@ -365,7 +365,7 @@ static void BM_vector_push_back(benchmark::State& state) {
} }
``` ```
Note that `ClobberMemory()` is only available for GNU based compilers. Note that `ClobberMemory()` is only available for GNU or MSVC based compilers.
### Set time unit manually ### Set time unit manually
If a benchmark runs a few milliseconds it may be hard to visually compare the If a benchmark runs a few milliseconds it may be hard to visually compare the
......
...@@ -165,6 +165,10 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); ...@@ -165,6 +165,10 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
#include <utility> #include <utility>
#endif #endif
#if defined(_MSC_VER)
#include <intrin.h> // for _ReadWriteBarrier
#endif
namespace benchmark { namespace benchmark {
class BenchmarkReporter; class BenchmarkReporter;
...@@ -215,11 +219,16 @@ BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams(); ...@@ -215,11 +219,16 @@ BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
} // end namespace internal } // end namespace internal
#if !defined(__GNUC__) || defined(__pnacl__) || defined(EMSCRIPTN)
# define BENCHMARK_HAS_NO_INLINE_ASSEMBLY
#endif
// The DoNotOptimize(...) function can be used to prevent a value or // The DoNotOptimize(...) function can be used to prevent a value or
// expression from being optimized away by the compiler. This function is // expression from being optimized away by the compiler. This function is
// intended to add little to no overhead. // intended to add little to no overhead.
// See: https://youtu.be/nXaxk27zwlk?t=2441 // See: https://youtu.be/nXaxk27zwlk?t=2441
#if defined(__GNUC__) && !defined(__pnacl__) && !defined(EMSCRIPTEN) #ifndef BENCHMARK_HAS_NO_INLINE_ASSEMBLY
template <class Tp> template <class Tp>
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
asm volatile("" : : "g"(value) : "memory"); asm volatile("" : : "g"(value) : "memory");
...@@ -229,12 +238,22 @@ inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { ...@@ -229,12 +238,22 @@ inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() { inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() {
asm volatile("" : : : "memory"); asm volatile("" : : : "memory");
} }
#elif defined(_MSC_VER)
template <class Tp>
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
_ReadWriteBarrier();
}
inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() {
_ReadWriteBarrier();
}
#else #else
template <class Tp> template <class Tp>
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value)); internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
} }
// FIXME Add ClobberMemory() for non-gnu compilers // FIXME Add ClobberMemory() for non-gnu and non-msvc compilers
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment