diff options
| author | Martin Hořeňovský | 2026-08-22 15:19:33 +0200 |
|---|---|---|
| committer | Martin Hořeňovský | 2026-08-22 20:43:13 +0200 |
| commit | 45f9ea1e798c2e128dcba53602ccbddfe5676f6f (patch) | |
| tree | 3eb107a59de8a5654109fc594ee29b3e5c57770d /src | |
| parent | 9915f7250dcfc2c7bbd9e86c83b29438df39d856 (diff) | |
| download | catch3-45f9ea1e798c2e128dcba53602ccbddfe5676f6f.tar.gz | |
Add optimizer barrier to benchmark calls of void-returning functions
The goal is to do the equivalent of clobbering memory, which forces
the compiler to keep side effects that are external to the benchmarked
function, while allowing it to optimize inside the benchmarked function.
E.g. this cannot be optimized away:
```cpp
BENCHMARK("foo") {
global_count += 1;
};
```
while this can:
```cpp
BENCHMARK("bar") {
size_t local_count = 0;
for (size_t i = 0; i < 100; ++i) {
local_count += 1;
}
};
```
Diffstat (limited to 'src')
| -rw-r--r-- | src/catch2/benchmark/catch_optimizer.hpp | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/src/catch2/benchmark/catch_optimizer.hpp b/src/catch2/benchmark/catch_optimizer.hpp index 61e6571f..5535b2a2 100644 --- a/src/catch2/benchmark/catch_optimizer.hpp +++ b/src/catch2/benchmark/catch_optimizer.hpp @@ -34,7 +34,7 @@ namespace Catch { } // namespace Detail #elif defined(_MSC_VER) || defined(__IAR_SYSTEMS_ICC__) -#if defined(_MSVC_VER) +#if defined(_MSC_VER) #pragma optimize("", off) #elif defined(__IAR_SYSTEMS_ICC__) // For IAR the pragma only affects the following function @@ -71,6 +71,13 @@ namespace Catch { template <typename Fn, typename... Args> inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> std::enable_if_t<std::is_same<void, decltype(fn(args...))>::value> { CATCH_FORWARD((fn)) (CATCH_FORWARD(args)...); + // In the non-void case, we pass the result through `deoptimize_value` + // to force the compiler to keep it. We have no return value here, + // but add an optimizer barrier (ideally a memory clobber) to force + // the _side effects_ of the loop be visible (e.g. writes to globals). + // Note that writes to benchmark-locals can be optimized away, as + // we would expect in normal code. + Detail::optimizer_barrier(); } } // namespace Benchmark } // namespace Catch |