diff --git a/README.md b/README.md index 456b0a6c..44466379 100644 --- a/README.md +++ b/README.md @@ -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 If a benchmark runs a few milliseconds it may be hard to visually compare the diff --git a/include/benchmark/benchmark_api.h b/include/benchmark/benchmark_api.h index f72a64a2..8cde61ba 100644 --- a/include/benchmark/benchmark_api.h +++ b/include/benchmark/benchmark_api.h @@ -165,6 +165,10 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #include #endif +#if defined(_MSC_VER) +#include // for _ReadWriteBarrier +#endif + namespace benchmark { class BenchmarkReporter; @@ -215,11 +219,16 @@ BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams(); } // 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 // expression from being optimized away by the compiler. This function is // intended to add little to no overhead. // See: https://youtu.be/nXaxk27zwlk?t=2441 -#if defined(__GNUC__) && !defined(__pnacl__) && !defined(EMSCRIPTEN) +#ifndef BENCHMARK_HAS_NO_INLINE_ASSEMBLY template inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { asm volatile("" : : "g"(value) : "memory"); @@ -229,12 +238,22 @@ inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() { asm volatile("" : : : "memory"); } +#elif defined(_MSC_VER) +template +inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { + internal::UseCharPointer(&reinterpret_cast(value)); + _ReadWriteBarrier(); +} + +inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() { + _ReadWriteBarrier(); +} #else template inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { internal::UseCharPointer(&reinterpret_cast(value)); } -// FIXME Add ClobberMemory() for non-gnu compilers +// FIXME Add ClobberMemory() for non-gnu and non-msvc compilers #endif