https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99693
--- Comment #1 from rafal at bursig dot org ---
I'm not saying that this is a regression because I see proper results on -O3
level but IMHO such results should be available in -O2 level... but to topic:
I have such code:
typedef struct Update {
int m_update;
//...
} Update;
extern void antagonizer( Update * );
void antagonize(Update *data, unsigned int n)
{
while(--n)
{
if (data->m_update)
{
antagonizer( data );
}
}
}
then -O2 level give me such asm:
antagonize:
sub esi, 1
je .L10
push rbp
mov rbp, rdi
push rbx
mov ebx, esi
sub rsp, 8
jmp .L4
.L3:
sub ebx, 1
je .L14
.L4:
mov eax, DWORD PTR [rbp+0]
test eax, eax
je .L3
mov rdi, rbp
call antagonizer
sub ebx, 1
jne .L4
.L14:
add rsp, 8
pop rbx
pop rbp
ret
.L10:
ret
Which is OK because the "antagonizer( data );" call can change "Update *data"
struct and the "if (data->m_update)" can't be moved outside loop.
But when If I create local copy of "data->m_update" then this check could be
moved outside loop without problem. But below code:
typedef struct Update {
int m_update;
//...
} Update;
extern void antagonizer( Update * );
void antagonize(Update *data, unsigned int n)
{
const int _update = data->m_update;
while(--n)
{
if (_update)
{
antagonizer( data );
}
}
}
Do not move "if (_update)" outside the loop and asm looks like:
antagonize:
push r12
push rbp
push rbx
mov ebp, DWORD PTR [rdi]
sub esi, 1
je .L1
mov r12, rdi
mov ebx, esi
jmp .L4
.L3:
sub ebx, 1
je .L1
.L4:
test ebp, ebp // the check
je .L3 // is still in loop
mov rdi, r12
call antagonizer
sub ebx, 1
jne .L4
.L1:
pop rbx
pop rbp
pop r12
ret
When I build this code with -O3 level then the check is moved out the loop
properly, but I got several others effects which I don't know if it will have
proper impact in my application (I will prefer stay with -O2). The asm for -O3
level:
antagonize:
mov eax, DWORD PTR [rdi]
sub esi, 1
je .L12
push rbp
mov rbp, rdi
push rbx
mov ebx, esi
sub rsp, 8
test eax, eax
jne .L3
.L1:
add rsp, 8
pop rbx
pop rbp
ret
.L3:
mov rdi, rbp
call antagonizer
sub ebx, 1
je .L1
mov rdi, rbp
call antagonizer
sub ebx, 1
jne .L3
jmp .L1
.L12:
ret