On Friday 30 August 2002 08:49, Daniel wrote:
> Sauf erreur, le compilateur est capable de d�tecter une
> division/multiplication par une constante puissance de 2, et de transformer
> cette op�ration en bit-shift �quivalent.
> Seul le r�sultat du bench nous dira si la t�orie se confirme :-)
Test sans bench, mais avec gcc 2.96 (i586) et Bastard v0.16.
Compilations avec Optimization -O3.
Pas C++, car le code produit ne serait pas aussi facilement lisible.
test1:
for (i=0;i<16;i++) {
a += w % 2;
w /= 2;
}
test2:
for (i=0;i<16;i++) {
a += w & 1;
w >>= 1;
}
test1 & test2:
080484B6 31 DB xor ebx , ebx ; a = 0
080484B8 8B 55 08 mov edx , [ebp+0x08] ; load w
080484BB 90 nop ; --
080484BC 8D 74 26 00 lea esi , [esi] ; --
080484C0 89 D0 mov eax , edx ; copy w
080484C2 D1 EA shr edx , 0x1 ; shift w
080484C4 83 E0 01 and eax , 0x1 ; test w
080484C7 41 inc ecx ; loop counter
080484C8 01 C3 add ebx , eax ; update a
080484CA 83 F9 0F cmp ecx , 0xF ; loop finished?
080484CD 76 F1 jbe...
Le code produit est identique dans les deux cas. Mais gcc n'arrive pour une
fois pas de remplacer inc ecx; cmp ecx, 0xF par un dec ecx.
Essayons de le forcer un peu:
test3a:
for (i=16;i>0;i--) {
a += w & 1;
w >>= 1;
}
08048531 B9 10 00 00 00 mov ecx , 0x10 ; load loop cnt
[...]
08048539 31 DB xor ebx , ebx ; a = 0
0804853B 8B 55 08 mov edx , [ebp+0x08] ; load w
0804853E 89 F6 mov esi , esi ; --
08048540 89 D0 mov eax , edx ; copy w
08048542 D1 EA shr edx , 0x1 ; shift w
08048544 83 E0 01 and eax , 0x1 ; test copy of w
08048547 01 C3 add ebx , eax ; update a
08048549 49 dec ecx ; loop counter
0804854A 75 F4 jnz ...
test3b:
for (i=16;i--;) {...}
Souvent vu comme recommondation. Je ne suis pas de cet avis, car c'est
traduit par
mov ecx, 0xF
Loop:
dec ecx
cmp ecx, -0x1
jnz Loop
Finalement la proposition de Marc:
test4:
while (w != 0) {
a += w & 1;
w >>= 1;
}
08048511 31 C9 xor ecx , ecx ; a = 0
08048513 89 E5 mov ebp , esp ;
08048515 8B 55 08 mov edx , [ebp+0x08] ; load w
08048518 85 D2 test edx , edx ; w already 0?
0804851A 74 0F jx
0804851C 8D 74 26 00 lea esi , [esi] ; --
08048520 89 D0 mov eax , edx ; copy w
08048522 83 E0 01 and eax , 0x1 ; test copy
08048525 01 C1 add ecx , eax ; update a
08048527 D1 EA shr edx , 0x1 ; shift w
08048529 75 F5 jnz ... ; w=0?
Bien d'accord que des autres principes peuvent etre plus efficaces.
btw une multiplication par deux est souvent traduit par add eax, eax.
Roman
--
http://www-internal.alphanet.ch/linux-leman/ avant de poser
une question. Ouais, pour se d�sabonner aussi.