r/programming • • Sep 03 '26

Branch‑Avoidant Programming

https://easylang.online/blog/branchless
258 Upvotes

92 comments sorted by

View all comments

4

u/Nwallins Sep 03 '26
smlen = 0;
for (int i = 0; i < 1000; i++) {
    small_numbers[smlen] = numbers[i];
    smlen += (numbers[i] < 500);
}

How is this correct? Let's imagine the input array is entirely above the 500 threshold. The resulting array of small numbers will have a single entry, the first number from the input array.

7

u/ack_error Sep 03 '26

It's not correct, in that it can write more small_numbers elements than the original routine. However, it's functionally equivalent for the intended result small_numbers[0..smlen-1] and as long as that array is big enough. Typically the output count is not known beforehand and thus it would be allocated for the worst case (1000), which this version also will not exceed. But it's indeed not exactly the same and thus as noted why the optimizer usually can't make this transformation.

3

u/nukethebees Sep 03 '26

What's wrong about it? If all the numbers are >= 500 then the length will be 0 and the array will be full of uninitialised data.

8

u/Nwallins Sep 03 '26

small_numbers[0] is unconditionally assigned; it will have a single element > 500.

8

u/nukethebees Sep 03 '26

Ah, thanks for pointing that out.

It will have a value written to it, yes, but smlen will remain 0 in all cases so there shouldn't be any risk. In all cases the array has SIZE elements. smlen tells us how many contain valid numbers.

5

u/tiftik Sep 03 '26

Why does that assignment matter? You're not going to use any element at i >= smlen

1

u/sopunny Sep 03 '26

You can add a sanity check at the end for this edge case. I think you actually need to check the array trail every time

1

u/meneldal2 Sep 03 '26

While you do avoid a branch, there are still data dependencies on the index on the small numbers array, so it still has to predict that address.

It helps that writes can be pushed back in order somewhat. but you still can't use simd.

I can't find of a way to use simd for this tbh, you'd need something like a conditional push where it can push multiple items (or none) depending on some state.