Interesting. I do know that some BPUs can disable branch prediction if it fails a few times (to say, given i % 2 == 0, it would disable branch prediction on the third or fourth iteration). I wasn't aware that they would actually go and find continuity in non-continuous branch behavior based on modulo alone, which isn't that common.
So let's run an experiment, shall we. Given Count = x.Length = 10000000 in C# (.NET, but the GC will never run):
Code:
for (var i = 0; i < Count; i += 1)
if (i % 2 == 0)
x[i] = 0;
else x[i] = 1;
Time: 55-80 milliseconds
Now the same functionality in two non-branching loops:
for (var i = 0; i < Count; i += 2)
x[i] = 0;
for (var i = 1; i < Count; i += 2)
x[i] = 1;
About 25-28 milliseconds. Now, to make it interesting, we do zero for the first half and one for the second half:
for (var i = 0; i < Count; i += 1)
if (i < Count / 2)
x[i] = 0;
else x[i] = 1;
40-42 milliseconds. Definitely, a coherent branch is much faster than an incoherent one, while no branching wins the day as always. (ok, not true, see edit).
Edit: so I was probably running into some jitter problems. Running the tests 20 times gives me 41 for the first, 21 for the second, and 39 for the last. So the first and last are comparable in time. Sorry for the sloppy benchmarking!
Edit 2: so if I take the Count/2 out of the loop, my numbers for the third test become fast again: 42 for the first, 19 for the second, 26 for the third (average time milliseconds for doing the loops 10 times). The comparison is still hardly fair since I'm not lifting the modulo out of the first loop, however. If I use a boolean that is continuously negated instead the modulo, the results are 29 for the first, which is much closer to the third.