Ich wäre mir da gar nicht mal so sicher, dass alle Versionen den gleichen Code erzeugen. Besonders das -1 in Swordfishs Version ist schwer weg zu optimieren (und ich hätte es auch ohne -1 programmiert:
std::size_t strlen( char const * str )
{
char const * p = str;
while( *p ) ++p;
return p - str;
}
)
Mal gucken, was GCC 4.8.2 auf O3 für x86-64 (aber ohne spezielle Prozessoroptimierungen) daraus macht:
Deine Version:
xorl %eax, %eax
cmpb $0, (%rdi)
je .L5
.p2align 4,,10
.p2align 3
.L6:
addq $1, %rax
cmpb $0, (%rdi,%rax)
jne .L6
.L5:
rep ret
Swordfish:
movq %rdi, %rax
.p2align 4,,10
.p2align 3
.L3:
addq $1, %rax
cmpb $0, -1(%rax)
jne .L3
subq %rdi, %rax
subq $1, %rax
ret
Meine Version:
cmpb $0, (%rdi)
je .L5
movq %rdi, %rax
.p2align 4,,10
.p2align 3
.L4:
addq $1, %rax
cmpb $0, (%rax)
jne .L4
subq %rdi, %rax
ret
.L5:
xorl %eax, %eax
ret
Wir sehen: Die Schleife selbst ist bei allen drei Versionen praktisch identisch (und das ist auch gut so!), aber die kleinen Dinge drumherum sind jeweils komplett unterschiedlich. Ich vermute sogar, dass Swordfishs Version hier theoretisch am schnellsten ist, weil ich die Effektivität der Prä-Prüfung, die für unsere beiden Versionen erzeugt wurde, anzweifle. Aber das ist ein sinnloser Vergleich einzelner Anweisungen, wenn der innere Loop praktisch identisch ist. Swordfish hat auf jeden Fall den Größenvergleich für den kürzesten Maschinencode gewonnen.