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