@@ -302,16 +302,97 @@ BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
302302// intended to add little to no overhead.
303303// See: https://youtu.be/nXaxk27zwlk?t=2441
304304#ifndef BENCHMARK_HAS_NO_INLINE_ASSEMBLY
305- template <class Tp >
306- inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize (Tp const & value) {
307- // Clang doesn't like the 'X' constraint on `value` and certain GCC versions
308- // don't like the 'g' constraint. Attempt to placate them both.
309305#if defined(__clang__)
310- asm volatile (" " : : " g" (value) : " memory" );
306+ template <class Tp >
307+ struct CanUseRegisterOperandImp {
308+ #ifdef BENCHMARK_HAS_CXX11
309+ using DecayT = typename std::decay<Tp>::type;
310+ static const bool value =
311+ sizeof (DecayT) <= sizeof (long );
311312#else
312- asm volatile (" " : : " i,r,m" (value) : " memory" );
313+ static const bool value = false ;
314+ #endif
315+ };
316+ template <class InputTp , bool = CanUseRegisterOperandImp<InputTp>::value>
317+ struct InlineAsmHelper {
318+ template <class Tp >
319+ static inline BENCHMARK_ALWAYS_INLINE
320+ void DoNotOptimize (Tp const & value) {
321+ asm volatile (" " : : " r,m" (value) : " memory" );
322+ }
323+ template <class Tp >
324+ static inline BENCHMARK_ALWAYS_INLINE
325+ void DoNotOptimize (Tp& value) {
326+ asm volatile (" " : " =g" (value) : : " memory" );
327+ }
328+ #ifdef BENCHMARK_HAS_CXX11
329+ template <class Tp >
330+ static inline BENCHMARK_ALWAYS_INLINE
331+ void DoNotOptimize (Tp&& value) {
332+ asm volatile (" " : : " r" (value) : " memory" );
333+ }
313334#endif
335+ };
336+ template <class InputTp >
337+ struct InlineAsmHelper <InputTp, false > {
338+ template <class Tp >
339+ static inline BENCHMARK_ALWAYS_INLINE
340+ void DoNotOptimize (Tp const & value) {
341+ asm volatile (" " : : " m" (value) : " memory" );
342+ }
343+ template <class Tp >
344+ static inline BENCHMARK_ALWAYS_INLINE
345+ void DoNotOptimize (Tp& value) {
346+ asm volatile (" " : " +m" (value) : : " memory" );
347+ }
348+ #ifdef BENCHMARK_HAS_CXX11
349+ template <class Tp >
350+ static inline BENCHMARK_ALWAYS_INLINE
351+ void DoNotOptimize (Tp&& value) {
352+ asm volatile (" " : : " r,m" (value) : " memory" );
353+ }
354+ #endif
355+ };
356+ #else
357+ template <class InputTp >
358+ struct InlineAsmHelper {
359+ template <class Tp >
360+ static inline BENCHMARK_ALWAYS_INLINE
361+ void DoNotOptimize (Tp const & value) {
362+ asm volatile (" " : : " r,m" (value) : " memory" );
363+ }
364+ template <class Tp >
365+ static inline BENCHMARK_ALWAYS_INLINE
366+ void DoNotOptimize (Tp& value) {
367+ asm volatile (" " : " +m,r" (value) : : " memory" );
368+ }
369+ #ifdef BENCHMARK_HAS_CXX11
370+ template <class Tp >
371+ static inline BENCHMARK_ALWAYS_INLINE
372+ void DoNotOptimize (Tp&& value) {
373+ asm volatile (" " : : " r,m" (value) : " memory" );
374+ }
375+ #endif
376+ };
377+ #endif
378+
379+ template <class Tp >
380+ inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize (Tp& value) {
381+ InlineAsmHelper<Tp>::DoNotOptimize (value);
382+ }
383+
384+ #if defined(BENCHMARK_HAS_CXX11)
385+ template <class Tp >
386+ inline BENCHMARK_ALWAYS_INLINE
387+ typename std::enable_if<!std::is_lvalue_reference<Tp>::value, void >::type
388+ DoNotOptimize (Tp&& value) {
389+ static_assert (!std::is_lvalue_reference<Tp>::value, " " );
390+ static_assert (!std::is_const<Tp>::value, " " );
391+ InlineAsmHelper<Tp>::DoNotOptimize (static_cast <Tp&&>(value));
314392}
393+
394+ template <class Tp > void DoNotOptimize (Tp const && value) = delete;
395+ #endif
315396// Force the compiler to flush pending writes to global memory. Acts as an
316397// effective read/write barrier
317398inline BENCHMARK_ALWAYS_INLINE void ClobberMemory () {
0 commit comments