1 /* 2 * Created by Joachim on 16/04/2019. 3 * Adapted from donated nonius code. 4 * 5 * Distributed under the Boost Software License, Version 1.0. (See accompanying 6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 */ 8 9 // Hinting the optimizer 10 11 #ifndef TWOBLUECUBES_CATCH_OPTIMIZER_HPP_INCLUDED 12 #define TWOBLUECUBES_CATCH_OPTIMIZER_HPP_INCLUDED 13 14 #if defined(_MSC_VER) 15 # include <atomic> // atomic_thread_fence 16 #endif 17 18 namespace Catch { 19 namespace Benchmark { 20 #if defined(__GNUC__) || defined(__clang__) 21 template <typename T> keep_memory(T * p)22 inline void keep_memory(T* p) { 23 asm volatile("" : : "g"(p) : "memory"); 24 } keep_memory()25 inline void keep_memory() { 26 asm volatile("" : : : "memory"); 27 } 28 29 namespace Detail { optimizer_barrier()30 inline void optimizer_barrier() { keep_memory(); } 31 } // namespace Detail 32 #elif defined(_MSC_VER) 33 34 #pragma optimize("", off) 35 template <typename T> 36 inline void keep_memory(T* p) { 37 // thanks @milleniumbug 38 *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p); 39 } 40 // TODO equivalent keep_memory() 41 #pragma optimize("", on) 42 43 namespace Detail { 44 inline void optimizer_barrier() { 45 std::atomic_thread_fence(std::memory_order_seq_cst); 46 } 47 } // namespace Detail 48 49 #endif 50 51 template <typename T> deoptimize_value(T && x)52 inline void deoptimize_value(T&& x) { 53 keep_memory(&x); 54 } 55 56 template <typename Fn, typename... Args> invoke_deoptimized(Fn && fn,Args &&...args)57 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<!std::is_same<void, decltype(fn(args...))>::value>::type { 58 deoptimize_value(std::forward<Fn>(fn) (std::forward<Args...>(args...))); 59 } 60 61 template <typename Fn, typename... Args> invoke_deoptimized(Fn && fn,Args &&...args)62 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<std::is_same<void, decltype(fn(args...))>::value>::type { 63 std::forward<Fn>(fn) (std::forward<Args...>(args...)); 64 } 65 } // namespace Benchmark 66 } // namespace Catch 67 68 #endif // TWOBLUECUBES_CATCH_OPTIMIZER_HPP_INCLUDED 69