Skip to content

Commit f682f7e

Browse files
authored
Implement ClobberMemory() and fix DoNotOptimize on MSVC. (google#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.
1 parent 8ae6448 commit f682f7e

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ static void BM_vector_push_back(benchmark::State& state) {
365365
}
366366
```
367367

368-
Note that `ClobberMemory()` is only available for GNU based compilers.
368+
Note that `ClobberMemory()` is only available for GNU or MSVC based compilers.
369369

370370
### Set time unit manually
371371
If a benchmark runs a few milliseconds it may be hard to visually compare the

include/benchmark/benchmark_api.h

+21-2
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
165165
#include <utility>
166166
#endif
167167

168+
#if defined(_MSC_VER)
169+
#include <intrin.h> // for _ReadWriteBarrier
170+
#endif
171+
168172
namespace benchmark {
169173
class BenchmarkReporter;
170174

@@ -215,11 +219,16 @@ BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
215219

216220
} // end namespace internal
217221

222+
223+
#if !defined(__GNUC__) || defined(__pnacl__) || defined(EMSCRIPTN)
224+
# define BENCHMARK_HAS_NO_INLINE_ASSEMBLY
225+
#endif
226+
218227
// The DoNotOptimize(...) function can be used to prevent a value or
219228
// expression from being optimized away by the compiler. This function is
220229
// intended to add little to no overhead.
221230
// See: https://youtu.be/nXaxk27zwlk?t=2441
222-
#if defined(__GNUC__) && !defined(__pnacl__) && !defined(EMSCRIPTEN)
231+
#ifndef BENCHMARK_HAS_NO_INLINE_ASSEMBLY
223232
template <class Tp>
224233
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
225234
asm volatile("" : : "g"(value) : "memory");
@@ -229,12 +238,22 @@ inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
229238
inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() {
230239
asm volatile("" : : : "memory");
231240
}
241+
#elif defined(_MSC_VER)
242+
template <class Tp>
243+
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
244+
internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
245+
_ReadWriteBarrier();
246+
}
247+
248+
inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() {
249+
_ReadWriteBarrier();
250+
}
232251
#else
233252
template <class Tp>
234253
inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
235254
internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
236255
}
237-
// FIXME Add ClobberMemory() for non-gnu compilers
256+
// FIXME Add ClobberMemory() for non-gnu and non-msvc compilers
238257
#endif
239258

240259

0 commit comments

Comments
 (0)