// Copyright 2015 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef BENCHMARK_UTILS_H_ #define BENCHMARK_UTILS_H_ #include #include #include #include "benchmark/export.h" #include "benchmark/macros.h" namespace benchmark { namespace internal { BENCHMARK_EXPORT void UseCharPointer(char const volatile*); } #if (!defined(__GNUC__) && !defined(__clang__)) || defined(__pnacl__) || \ defined(__EMSCRIPTEN__) #define BENCHMARK_HAS_NO_INLINE_ASSEMBLY #endif inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() { std::atomic_signal_fence(std::memory_order_acq_rel); } #define BENCHMARK_DONOTOPTIMIZE_CONST_REF_DEPRECATED_MSG \ "DoNotOptimize(T const&) can permit undesired compiler optimizations. " \ "Pass a non-const lvalue instead; if the argument is an expression result, " \ "store it in a local variable first." #ifndef BENCHMARK_HAS_NO_INLINE_ASSEMBLY #if !defined(__GNUC__) || defined(__llvm__) || defined(__INTEL_COMPILER) template BENCHMARK_DEPRECATED_MSG(BENCHMARK_DONOTOPTIMIZE_CONST_REF_DEPRECATED_MSG) inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { asm volatile("" : : "r,m"(value) : "memory"); } template inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) { #if defined(__clang__) asm volatile("" : "+r,m"(value) : : "memory"); #else asm volatile("" : "+m,r"(value) : : "memory"); #endif } template inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) { #if defined(__clang__) asm volatile("" : "+r,m"(value) : : "memory"); #else asm volatile("" : "+m,r"(value) : : "memory"); #endif } #elif (__GNUC__ >= 5) template BENCHMARK_DEPRECATED_MSG(BENCHMARK_DONOTOPTIMIZE_CONST_REF_DEPRECATED_MSG) inline BENCHMARK_ALWAYS_INLINE typename std::enable_if::value && (sizeof(Tp) <= sizeof(Tp*))>::type DoNotOptimize(Tp const& value) { asm volatile("" : : "r,m"(value) : "memory"); } template BENCHMARK_DEPRECATED_MSG(BENCHMARK_DONOTOPTIMIZE_CONST_REF_DEPRECATED_MSG) inline BENCHMARK_ALWAYS_INLINE typename std::enable_if::value || (sizeof(Tp) > sizeof(Tp*))>::type DoNotOptimize(Tp const& value) { asm volatile("" : : "m"(value) : "memory"); } template inline BENCHMARK_ALWAYS_INLINE typename std::enable_if::value && (sizeof(Tp) <= sizeof(Tp*))>::type DoNotOptimize(Tp& value) { asm volatile("" : "+m,r"(value) : : "memory"); } template inline BENCHMARK_ALWAYS_INLINE typename std::enable_if::value || (sizeof(Tp) > sizeof(Tp*))>::type DoNotOptimize(Tp& value) { asm volatile("" : "+m"(value) : : "memory"); } template inline BENCHMARK_ALWAYS_INLINE typename std::enable_if::value && (sizeof(Tp) <= sizeof(Tp*))>::type DoNotOptimize(Tp&& value) { asm volatile("" : "+m,r"(value) : : "memory"); } template inline BENCHMARK_ALWAYS_INLINE typename std::enable_if::value || (sizeof(Tp) > sizeof(Tp*))>::type DoNotOptimize(Tp&& value) { asm volatile("" : "+m"(value) : : "memory"); } #endif #elif defined(_MSC_VER) template BENCHMARK_DEPRECATED_MSG(BENCHMARK_DONOTOPTIMIZE_CONST_REF_DEPRECATED_MSG) inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { internal::UseCharPointer(&reinterpret_cast(value)); ClobberMemory(); } template inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) { internal::UseCharPointer(&reinterpret_cast(value)); ClobberMemory(); } template inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) { internal::UseCharPointer(&reinterpret_cast(value)); ClobberMemory(); } #else template inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp&& value) { internal::UseCharPointer(&reinterpret_cast(value)); } #endif #undef BENCHMARK_DONOTOPTIMIZE_CONST_REF_DEPRECATED_MSG } // end namespace benchmark #endif // BENCHMARK_UTILS_H_