• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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