[BUG] DoNotOptimize unpredictable on ternary conditionals
- Dominant language
- C++
- Stars
- 10.4k
- Forks
- 1.8k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 8
Description
**Describe the bug**
DoNotOptimize seems to have unpredictable behavior on ternary conditionals.
I'm trying to benchmark the performance of manual flushing to zero on denormals and I define a macro like this:
```c++
#include
#include
#define FLUSHF(x) ((x) = fabsf(x)
#include
#include
#define FLUSHF(x) ((x) = fabsf(x)
inline void escape(Tp& value)
{
asm volatile("" : : "g"(value) : "memory");
}
```
and it works correctly. Try compile the following to see the problem:
```c++
#include
#include
#include
#define FLUSH(x) ((x) = fabs(x)
inline void escape(Tp& value)
{
asm volatile("" : : "g"(value) : "memory");
}
static void
flush_64(benchmark::State& state)
{
double mem = FLT_MIN;
for (auto _ : state) {
benchmark::DoNotOptimize(mem = 0.999 * mem);
benchmark::DoNotOptimize(FLUSH(mem));
}
}
BENCHMARK(flush_64);
static void
flush_32(benchmark::State& state)
{
float mem = FLT_MIN;
for (auto _ : state) {
benchmark::DoNotOptimize(mem = 0.999f * mem);
benchmark::DoNotOptimize(FLUSHF(mem));
}
}
BENCHMARK(flush_32);
static void
escape_32(benchmark::State& state)
{
float mem = FLT_MIN;
for (auto _ : state) {
benchmark::DoNotOptimize(mem = 0.999f * mem);
escape(FLUSHF(mem));
}
}
BENCHMARK(escape_32);
BENCHMARK_MAIN();
```
```console
$ g++ -O3 bug.cc -lbenchmark
$ ./a.out
-----------------------------------------------------
Benchmark Time CPU Iterations
-----------------------------------------------------
flush_64 0.606 ns 0.605 ns 995985269
flush_32 37.5 ns 37.5 ns 18310441
escape_32 0.773 ns 0.772 ns 901474201
$ g++ -O2 bug.cc -lbenchmark
$ ./a.out
-----------------------------------------------------
Benchmark Time CPU Iterations
-----------------------------------------------------
flush_64 5.94 ns 5.94 ns 101705109
flush_32 6.12 ns 6.11 ns 115467957
escape_32 4.65 ns 4.64 ns 152872058
$ clang++ -O3 bug.cc -lbenchmark
$ ./a.out
-----------------------------------------------------
Benchmark Time CPU Iterations
-----------------------------------------------------
flush_64 5.24 ns 5.24 ns 99614101
flush_32 5.34 ns 5.34 ns 130798955
escape_32 5.35 ns 5.35 ns 129643413
$ clang++ -O2 bug.cc -lbenchmark
$ ./a.out
-----------------------------------------------------
Benchmark Time CPU Iterations
-----------------------------------------------------
flush_64 5.33 ns 5.24 ns 98349666
flush_32 5.38 ns 5.27 ns 132894039
escape_32 5.44 ns 5.44 ns 129066762
```
The anomaly of `flush_32` with `gcc -O3` is apparently a problem.
Is there a way to fix this problem without manually introducing another non-portable function to escape the optimization?
**System**
Which OS, compiler, and compiler version are you using:
- OS: Linux 5.12.12
- Compiler and version: g++ 11.1.0, clang++ 12.0.0
**Expected behavior**
DoNotOptimize works predictably on ternary conditionals.
Contributor guide
Assessment
This issue has not been assessed yet.