Prawie każda zmienna register jest chowana w rejestrze. Zależnie od kompilatora pekfosie, GCC udostępnia tylko 1 czy tam 2 rejestry. |
co
W dzisiejszych kompilatorach
register nie ma praktycznie żadnego wpływu na generowany kod. Weźmy na przykład taki bezsensowny kod:
#ifdef USE_REGISTER
# define REGISTER register
#else
# define REGISTER
#endif
int g( REGISTER int x );
void f( REGISTER int * array, REGISTER int size ) {
for( REGISTER int i = 0; i < size; ++i ) {
REGISTER int value = array[ i ];
REGISTER int new_value = g( value );
array[ i ] =( new_value != 0 ) ? new_value
: value;
}
}
Sprawdźmy różnice między wygenerowanym kodem po kompilacji z i bez USE_REGISTER:
>> diff -u <(clang -O0 -S -o - test.cc) <(clang -O0 -S -o - test.cc -DUSE_REGISTER)
>>
…no tak. Pod Clangiem wygenerowany kod jest identyczny. Może pod GCC
register zrobi jakąś różnicę?
>> diff -u <(gcc -O0 -S -o - test.cc) <(gcc -O0 -S -o - test.cc -DUSE_REGISTER)
--- /proc/self/fd/11 2015-10-15 18:23:13.678993414 +0200
+++ /proc/self/fd/12 2015-10-15 18:23:13.678993414 +0200
@@ -10,43 +10,52 @@
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
- subq $32, %rsp
- movq %rdi, -24(%rbp)
- movl %esi, -28(%rbp)
- movl $0, -4(%rbp)
+ pushq %r15
+ pushq %r14
+ pushq %r13
+ pushq %r12
+ pushq %rbx
+ subq $8, %rsp
+ .cfi_offset 15, -24
+ .cfi_offset 14, -32
+ .cfi_offset 13, -40
+ .cfi_offset 12, -48
+ .cfi_offset 3, -56
+ movq %rdi, %r13
+ movl %esi, %r15d
+ movl $0, %ebx
.L5:
- movl -4(%rbp), %eax
- cmpl -28(%rbp), %eax
+ cmpl %r15d, %ebx
jge .L6
- movl -4(%rbp), %eax
- cltq
- leaq 0(,%rax,4), %rdx
- movq -24(%rbp), %rax
- addq %rdx, %rax
- movl (%rax), %eax
- movl %eax, -8(%rbp)
- movl -8(%rbp), %eax
- movl %eax, %edi
+ movslq %ebx, %rax
+ salq $2, %rax
+ addq %r13, %rax
+ movl (%rax), %r12d
+ movl %r12d, %edi
call _Z1gi
- movl %eax, -12(%rbp)
- movl -4(%rbp), %eax
- cltq
- leaq 0(,%rax,4), %rdx
- movq -24(%rbp), %rax
- addq %rax, %rdx
- cmpl $0, -12(%rbp)
+ movl %eax, %r14d
+ movslq %ebx, %rax
+ salq $2, %rax
+ addq %r13, %rax
+ testl %r14d, %r14d
je .L3
- movl -12(%rbp), %eax
+ movl %r14d, %edx
jmp .L4
.L3:
- movl -8(%rbp), %eax
+ movl %r12d, %edx
.L4:
- movl %eax, (%rdx)
- addl $1, -4(%rbp)
+ movl %edx, (%rax)
+ addl $1, %ebx
jmp .L5
.L6:
nop
- leave
+ addq $8, %rsp
+ popq %rbx
+ popq %r12
+ popq %r13
+ popq %r14
+ popq %r15
+ popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
>>
Faktycznie, jest różnica. Co jednak się stanie, jeśli włączymy
jakiekolwiek optymalizacje?
>> diff -u <(gcc -Og -S -o - test.cc) <(gcc -Og -S -o - test.cc -DUSE_REGISTER)
>>
Jak się okazuje, pod GCC wystarczy włączyć optymalizacje, by
register przestało mieć wpływ.