I guess while Python interprets this branchless code it still can do some branching? Or am I missing something here?
begin += (arr[step+begin] < value)?step:0;
Something like: int mask = ((arr[step + begin] - value) >> 31); //Depends on signed shift
begin += (step & mask) | (0 & ~mask);
(Obviously in this case, it's simplifiable.) for (step >>= 1; step != 0; step >>=1) {
if ((next = begin + step) < size) {
begin += PyObject_RichCompareBool(PyList_GetItem(list_obj, next), value, Py_LT) * step;
}
}If there's no calculation being done, it'll simplify.
value = (test) ? const0 : const1;
But if calculations are being done, it won't. value = (test) ? calc0() : calc1();
If you want non-branching where the ternary options are calculated, you need to calculate both.This matters most with SIMD operations.
Look at section 2.5.1 (Branch-Equivalent SIMD Processing)
http://ftp.cvut.cz/kernel/people/geoff/cell/ps3-linux-docs/C...
There's probably something at the instruction level which allows the constant ternary expressions to be non-branching.
Even removing the UB with something like __builtin_sub_overflow(), if arr[...] is INT_MAX and value is -2, then the difference will have the high bit set!
I haven't tried it, but this should compile to a cmove or seta, not a jump:
int cond = arr[step+begin] < value;
begin += step & -cond; int mask = -(arr[step+begin] < value);
int value = (val0 & mask)|(val1 & ~mask);