catch_optimizer.hpp 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  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. // Hinting the optimizer
  9. #ifndef TWOBLUECUBES_CATCH_OPTIMIZER_HPP_INCLUDED
  10. #define TWOBLUECUBES_CATCH_OPTIMIZER_HPP_INCLUDED
  11. #if defined(_MSC_VER)
  12. # include <atomic> // atomic_thread_fence
  13. #endif
  14. namespace Catch {
  15. namespace Benchmark {
  16. #if defined(__GNUC__) || defined(__clang__)
  17. template <typename T>
  18. inline void keep_memory(T* p) {
  19. asm volatile("" : : "g"(p) : "memory");
  20. }
  21. inline void keep_memory() {
  22. asm volatile("" : : : "memory");
  23. }
  24. namespace Detail {
  25. inline void optimizer_barrier() { keep_memory(); }
  26. } // namespace Detail
  27. #elif defined(_MSC_VER)
  28. #pragma optimize("", off)
  29. template <typename T>
  30. inline void keep_memory(T* p) {
  31. // thanks @milleniumbug
  32. *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p);
  33. }
  34. // TODO equivalent keep_memory()
  35. #pragma optimize("", on)
  36. namespace Detail {
  37. inline void optimizer_barrier() {
  38. std::atomic_thread_fence(std::memory_order_seq_cst);
  39. }
  40. } // namespace Detail
  41. #endif
  42. template <typename T>
  43. inline void deoptimize_value(T&& x) {
  44. keep_memory(&x);
  45. }
  46. template <typename Fn, typename... Args>
  47. inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<!std::is_same<void, decltype(fn(args...))>::value>::type {
  48. deoptimize_value(std::forward<Fn>(fn) (std::forward<Args...>(args...)));
  49. }
  50. template <typename Fn, typename... Args>
  51. inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<std::is_same<void, decltype(fn(args...))>::value>::type {
  52. std::forward<Fn>(fn) (std::forward<Args...>(args...));
  53. }
  54. } // namespace Benchmark
  55. } // namespace Catch
  56. #endif // TWOBLUECUBES_CATCH_OPTIMIZER_HPP_INCLUDED