24.03.2006

Вы будете смеяться, но...

...продолжение swap-эпопеи
В ходе обсуждения с одним из коллег-начальников, попробовал вставить swap в какой-нибудь контест.

C source


int get_gcd( int a, int b )
{
while (1)
{
if (b == 0)
return a;
a %= b;
a ^= b ^= a ^= b;
}
}

int get_gcd_2( int a, int b )
{
while (1)
{
if (b == 0)
return a;
a %= b;
{
int c = a;
a = b;
b = c;
}
}
}








RVCT codeGCC code
get_gcd PROC
PUSH {r4,lr}
MOV r4,r1
|L1.8|
CMP r4,#0
POPEQ {r4,pc}
MOV r1,r4
BL __aeabi_idivmod
EOR r0,r1,r4
EOR r4,r0,r4
EOR r0,r4,r0

B |L1.8|
ENDP

get_gcd_2 PROC
PUSH {r4,lr}
B |L1.68|
|L1.48|
CMP r4,#0
POPEQ {r4,pc}
MOV r1,r4
BL __aeabi_idivmod
MOV r0,r4
|L1.68|
MOV r4,r1

B |L1.48|
ENDP
get_gcd:
mov ip, sp
stmfd sp!, {r4, fp, ip, lr, pc}
sub fp, ip, #4
mov r4, r1
.L4:
cmp r4, #0
beq .L5
mov r1, r4
bl __modsi3
eor r0, r0, r4
eor r4, r4, r0
eor r0, r0, r4

b .L4
.L5:
ldmea fp, {r4, fp, sp, lr}
bx lr

get_gcd_2:
mov ip, sp
stmfd sp!, {r4, fp, ip, lr, pc}
sub fp, ip, #4
mov r4, r1
.L10:
cmp r4, #0
beq .L11
mov r1, r4
bl __modsi3
mov r3, r0
mov r0, r4
mov r4, r3

b .L10
.L11:
ldmea fp, {r4, fp, sp, lr}
bx lr




C source


void swap_memory( int* array, int len )
{
int i;

for (i = 0; i < (len / 1); i++)
{
array[i] ^= array[len - i - 1] ^= array[i] ^= array[len - i - 1];
}
}

void swap_memory_2( int* array, int len )
{
int i;

for (i = 0; i < (len / 1); i++)
{
int c = array[i];
array[i] = array[len - i - 1];
array[len - i - 1] = c;
}
}








RVCT codeGCC code
swap_memory PROC
MOV r2,#0
PUSH {lr}
B |L1.64|
|L1.12|
SUB r3,r1,r2
ADD r3,r0,r3,LSL #2
LDR lr,[r3,#-4]
LDR r12,[r0,r2,LSL #2]
EOR r12,r12,lr
STR r12,[r0,r2,LSL #2]
LDR lr,[r3,#-4]
EOR r12,r12,lr
STR r12,[r3,#-4]
LDR r3,[r0,r2,LSL #2]
EOR r3,r12,r3
STR r3,[r0,r2,LSL #2]

ADD r2,r2,#1
|L1.64|
CMP r2,r1
BLT |L1.12|
POP {pc}
ENDP

swap_memory_2 PROC
MOV r2,#0
PUSH {lr}
|L1.84|
CMP r2,r1
POPGE {pc}
SUB r12,r1,r2
ADD r12,r0,r12,LSL #2
LDR lr,[r12,#-4]
LDR r3,[r0,r2,LSL #2]
STR lr,[r0,r2,LSL #2]

ADD r2,r2,#1
STR r3,[r12,#-4]
B |L1.84|
ENDP
swap_memory:
mov ip, sp
stmfd sp!, {r4, r5, r6, fp, ip, lr, pc}
sub fp, ip, #4
mov lr, #0
mov r4, r1
cmp lr, r4
mov r5, r0
bge .L3
mvn r6, #3
mov ip, r5
.L5:
ldr r0, [ip, #0]
rsb r1, lr, r4
add r1, r5, r1, asl #2
ldr r3, [r1, r6]
eor r0, r0, r3
str r0, [ip, #0]
ldr r2, [r1, r6]
eor r2, r2, r0
str r2, [r1, r6]
ldr r3, [ip, #0]
eor r3, r3, r2
str r3, [ip], #4

add lr, lr, #1
cmp lr, r4
blt .L5
.L3:
ldmea fp, {r4, r5, r6, fp, sp, lr}
bx lr

swap_memory_2:
mov ip, sp
stmfd sp!, {r4, r5, fp, ip, lr, pc}
sub fp, ip, #4
mov ip, #0
mov r4, r1
cmp ip, r4
bge .L9
mvn r5, #3
mov lr, r0
.L11:
rsb r3, ip, r4
add r3, r0, r3, asl #2
ldr r2, [r3, r5]
ldr r1, [lr, #0]
str r2, [lr], #4
str r1, [r3, r5]

add ip, ip, #1
cmp ip, r4
blt .L11
.L9:
ldmea fp, {r4, r5, fp, sp, lr}
bx lr


В общем, для себя я сделал вывод - лучше не выпендриваться, использовать дополнительную переменную и не мешать компилятору самому оптимизировать данный кусок кода.

3 комментария: