Набросал вот небольшой тестовый код, и попробовал собрать его третьим и четвертым gcc. Ключ у обоих -O3.
Четвёртый показал примерно то что я и ожидал — внутренности небольшого класса созданого в локальном контексте полностью соптимизировались. А вот третий не сделал практически ничего, за исключением инлайна методов.
Так что стало интересно, что это за конкретная опция оптимизации, когда она появилась, и нет ли возможности улучшить поведение gcc3
Исходный код:
#include <pthread.h>
extern pthread_mutex_t mutex;
class scopedlock
{
pthread_mutex_t *mutex;
bool need_unlock;
public:
scopedlock(pthread_mutex_t *mtx): mutex(mtx), need_unlock(true) { pthread_mutex_lock(mutex); }
~scopedlock() { unlock(); }
void unlock()
{
if (need_unlock) {
pthread_mutex_unlock(mutex);
need_unlock = false;
}
}
};
int t1(int a, char *b)
{
scopedlock guard(&mutex);
if (a == 5) {
return 3;
}
*b = 7;
return 8;
}
Результат gcc4
t1(int, char*):
pushl %ebp
movl %esp, %ebp
pushl %ebx
movl $3, %ebx
subl $4, %esp
movl $_mutex, (%esp)
call _pthread_mutex_lock
cmpl $5, 8(%ebp)
je L3
movl 12(%ebp), %eax
movl $8, %ebx
movb $7, (%eax)
L3:
movl $_mutex, (%esp)
call _pthread_mutex_unlock
movl %ebx, %eax
addl $4, %esp
popl %ebx
popl %ebp
ret
Результат gcc3
t1(int, char*):
pushl %ebp
movl %esp, %ebp
subl $40, %esp Что-то я вообще запутался, почему 40?
movl $_mutex, -24(%ebp) Создали экземпляр scopedlock на стеке
movb $1, -20(%ebp)
movl $_mutex, (%esp)
call _pthread_mutex_lock
cmpl $5, 8(%ebp)
je L17
movl 12(%ebp), %edx
movb $7, (%edx)
cmpb $0, -20(%ebp) Сравниваем -20(%ebp) с 0, хотя только что туда 1 записали. И это хваленый -O3?
jne L18
movl $8, %eax
L4:
L1:
leave
ret
.p2align 4,,7
L18:
movl -24(%ebp), %ecx
movl %ecx, (%esp)
call _pthread_mutex_unlock
movb $0, -20(%ebp)
movl $8, %eax
jmp L1
.p2align 4,,7
L17:
cmpb $0, -20(%ebp)
jne L19
movl $3, %eax
L20:
leave
ret
L19:
movl -24(%ebp), %eax
movl %eax, (%esp)
call _pthread_mutex_unlock Анлока теперь два для каждого return
movb $0, -20(%ebp)
movl $3, %eax
jmp L20