F
@hustbaer sagte in branchless programming:
unsigned char x = uch;
x |= x >> 4;
x |= x >> 2;
x |= x >> 1;
x &= 1;
p += x;
Nachdem ich endlich gerafft habe, dass all diese Zeilen nur dafür da sind, um die Nullterminierung zu behandeln, hab ich mich gefragt, ob sich das statt kreativ pfiffig nicht auch langweilig simpel formulieren lässt.
Auf (x86) CPU-Ebene gedacht kann man für "branchless" ja durchaus die CMP-Instruktion verwenden, nur eben ohne den sonst üblicherweise folgenden bedingten Sprung - man muss lediglich die von CMP gesetzten Flags auslesen.
Und tatsächlich, ein simples p += (x == 0); sollte es hier auch tun:
bool cmp(int a, int b)
{
return a == b;
}
==> https://godbolt.org/z/jGb3WE
cmp(int, int):
cmp edi, esi
sete al
ret
Ob das für andere CPUs auch so schön geht, kann ich nicht sagen, für x86 macht es den Code jedenfalls kürzer und lesbarer.
Edit: Ich hatte schon den Verdacht, dass das eventuell nicht mit jeder CPU-Architektur geht. Für ARM sieht mir das immer noch "branchless" aus, aber AVR gcc 9.2.0 erzeugt hier:
cmp(int, int):
mov r19,r25
mov r18,r24
ldi r24,lo8(1)
cp r18,r22
cpc r19,r23
breq .L2
ldi r24,0
.L2:
ret
breq scheint mir ein bedingter Sprung zu sein. Ich denke das Bitgefummel ist wohl letztendlich doch zuverlässiger.