Hacker News new | ask | show | jobs
by dathinab 1302 days ago
Anything between nothing and one most likely correct branch predicted to _not_ jump "branch iff int/pointer > int/pointer".

This kind of bounds check are normally not ever violated (in well formed code) so branch prediction predicts them correctly nearly always.

It also is (normally) just jumping in the bad case, which means with a correct branch predictions thy can be really cheap.

And then cpu "magic" tends to be optimized for that kind of checks at they appear in a lot of languages (e.g. Java).

Then in many cases the compiler can eliminate the checks partially.

For example any many kinds of for-each element iterations the compiler can infer that the result of the conditionally loop continuation check implies the bounds check. Combine that with loop unrolling which can reduce the number of continuation checks and you might end up with even less.

Also bounds checks tend to be an emergency guard, so you tend to sometimes do checks yourself before indexing and the compiler can often use that to eliminate the bounds check.

And even if you ignore all optimizations it's (assuming in bounds) "just" at most one int/pointer cmp (cheap) followed by a conditional branch which doesn't branch (cheap).

1 comments

Branches add control flow which can inhibit other optimizations, such as vectorization. Compare the codegen of these two functions to double the first 64 elements in a u8 slice: https://rust.godbolt.org/z/hccWGv889

The unchecked version is fully unrolled and vectorized using multiple registers. The checked version must use a loop.

Part of what's going on here is that panics are "recoverable." If the out-of-bounds write occurs at index 61, this will panic, but the writes to lower indexes must have gone through. This means the panic cannot be hoisted out of the loop.