@@ -302,16 +302,98 @@ 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+ typename std::enable_if<!std::is_lvalue_reference<Tp>::value, void >::type
373+ DoNotOptimize (Tp&& value) {
374+ asm volatile (" " : : " r,m" (value) : " memory" );
375+ }
376+ #endif
377+ };
378+ #endif
379+
380+ template <class Tp >
381+ inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize (Tp& value) {
382+ InlineAsmHelper<Tp>::DoNotOptimize (value);
383+ }
384+
385+ #if defined(BENCHMARK_HAS_CXX11)
386+ template <class Tp >
387+ inline BENCHMARK_ALWAYS_INLINE
388+ typename std::enable_if<!std::is_lvalue_reference<Tp>::value, void >::type
389+ DoNotOptimize (Tp&& value) {
390+ static_assert (!std::is_lvalue_reference<Tp>::value, " " );
391+ static_assert (!std::is_const<Tp>::value, " " );
392+ InlineAsmHelper<Tp>::DoNotOptimize (static_cast <Tp&&>(value));
314393}
394+
395+ template <class Tp > void DoNotOptimize (Tp const && value) = delete;
396+ #endif
315397// Force the compiler to flush pending writes to global memory. Acts as an
316398// effective read/write barrier
317399inline BENCHMARK_ALWAYS_INLINE void ClobberMemory () {
0 commit comments