Skip to content

Instantly share code, notes, and snippets.

@gnzlbg
Last active February 19, 2019 16:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gnzlbg/450931d141fa7d786a2a2a6b2ad459c2 to your computer and use it in GitHub Desktop.
Save gnzlbg/450931d141fa7d786a2a2a6b2ad459c2 to your computer and use it in GitHub Desktop.

So @eddyb and me talked about this, and this comment summarizes that.

@eddyb proposes a bench_input function with the operational semantics of the identity function, that the optimizer is encouraged / hinted to treat as an unknown pure function (think extern { const fn bench_input<T>(T) -> T; }).

That is, the statement bench_input(expr); can be completely optimized away. Given:

let mut v = Vec::with_capacity(1);
v.push(1);
let v = bench_input(v); 
v[0];

the bound check in v[0] cannot be removed because bench_input could return any vector (e.g. Vec::new()). Also, because the return value depends on the input, the write of 1 to memory in the push must be flushed before calling bench_input.

However, because the v[0]; result is not used, that could be optimized away, and because v is not used, and bench_input is pure, actually the whole snippet can be optimized away.

To prevent that from happening, @eddyb proposes to add bench_output(x), which has the same operational semantics as mem::forget: it leaks its value, runs no destructors, but which the optimizer is encouraged to treat as an unknown function with read-only side-effects that depend on x.

With that, one can change the snippet above to:

let mut v = Vec::with_capacity(1);
v.push(1);
let v = bench_input(v); 
bench_output(v[0]);

to prevent the code from being removed.

Note: bench_output cannot be implemented as fn bench_output<T>(x: T) { bench_input(x); }, because that would mean that it can be removed. It must therefore be a special API.

Something like black_box, as proposed in this RFC, would then be implemented as:

fn black_box<T>(x: T) -> T {
    bench_output(&x);
    bench_input(x)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment