Compiler For statement optimization
Under what conditions does the compiler optimize For statements?
The articles written on this blog were created with the goal of teaching. Also, the information in the article may be incorrect, so please be careful.
From the CPU's perspective, the JMP instruction used in the For statement is: Because performance degradation occurs when the pipeline is broken or branch prediction fails, The compiler tries not to use JMP instructions if the conditions are met.
- When the number of iterations is confirmed as a constant at compile time.
Optimizable: for (int i = 0; i < 4; i++) (knowing it will be repeated 4 times) Optimization difficulty: for (int i = 0; i < n; i++) (if n is a variable determined at runtime)
//original code
for (int i = 0; i < 3; i++) {
arr[i] = 0;
}
//After compiler optimization
arr[0] = 0;
arr[1] = 0;
arr[2] = 0;
Assembly language before optimization
.L2:
cmp DWORD PTR [rbp-4], 2 ;Compare if i < 3
jg .L3 ;If the conditions are not met, the loop ends (jump to L3).
mov eax, DWORD PTR [rbp-4]
cdqe
mov DWORD PTR [rbp-32+rax*4], 0 ;arr[i] = 0 assignment
add DWORD PTR [rbp-4], 1 ; i++
jmp .L2 ;Unconditional jump back to loop start point (.L2) (JMP)
.L3:
Optimized assembly language
mov DWORD PTR [rdi], 0 ; arr[0] = 0
mov DWORD PTR [rdi+4], 0 ;arr[1] = 0 (+4 because int is 4 bytes)
mov DWORD PTR [rdi+8], 0 ;arr[2] = 0 (+8 because int is 4 bytes)
- When the final result can be calculated in advance at compile time.
When the logic inside the loop does not depend on external inputs and outputs, the result value is replaced with a constant.
//original code
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
//After compiler optimization
//JMP does not even perform addition operations at runtime.
return 5050;
Assembly language before optimization
.L5:
cmp DWORD PTR [rbp-4], 100 ;Compare if i <= 100
jg .L6 ;Or end the loop
mov eax, DWORD PTR [rbp-4]
add DWORD PTR [rbp-8], eax ; sum += i
add DWORD PTR [rbp-4], 1 ; i++
jmp .L5 ;Jump back to loop start (.L5) (JMP)
.L6:
mov eax, DWORD PTR [rbp-8] ;Preparing to return results
Assembly language after optimization
mov eax, 5050 ;Insert the calculated result value 5050 into the eax register.
ret ;return immediately
- When the code length is short even with loop expansion.
Expanding a loop like code 1 is called loop expansion or Loop Unrolling. If the code length becomes too long due to loop expansion, it is a waste of the CPU's instruction cache memory. If the code size inside the loop is not small, Loop Unrolling is not optimized.
- When there is no complex control flow inside the loop.
There is a break, continue, goto, or complex if-else statement inside the loop, or If an external function call is included, the compiler does not expand the loop carelessly.
If there is an I/O function such as printf, Since we must protect the side effects displayed on the screen, we honestly run through JMP and call the function without omitting the loop.
Additionally, the compiler optimization option must be turned on to attempt optimization as above.