This question is in part a follow up question to GCC 5.1 Loop unrolling.
According to the GCC documentation, and as stated in my answer to the above question, flags such as -funroll-loops
turn on "complete loop peeling (i.e. complete removal of loops with a small constant number of iterations)". Therefore, when such a flag is enabled, the compiler can choose to unroll a loop if it determines that this would optimise the execution of a given piece of code.
Nevertheless, I noticed in one of my projects that GCC would sometimes unroll loops even though the relevant flags were not enabled. For instance, consider the following simple piece of code:
int main(int argc, char **argv)
{
int k = 0;
for( k = 0; k < 5; ++k )
{
volatile int temp = k;
}
}
When compiling with -O1
, the loop is unrolled and the following assembly code is generated with any modern version of GCC:
main:
movl $0, -4(%rsp)
movl $1, -4(%rsp)
movl $2, -4(%rsp)
movl $3, -4(%rsp)
movl $4, -4(%rsp)
movl $0, %eax
ret
Even when compiling with the additional -fno-unroll-loops -fno-peel-loops
to make sure the flags are disabled, GCC unexpectedly still performs loop unrolling on the example described above.
This observation leads me to the following closely related questions. Why does GCC perform loop unrolling even though the flags corresponding to this behaviour are disabled? Is unrolling also controlled by other flags which can make the compiler unroll a loop in some cases even though -funroll-loops
is disabled? Is there a way to completely disable loop unrolling in GCC (a part from compiling with -O0
)?
Interestingly the Clang compiler has the expected behaviour here, and seems to only perform unrolling when -funroll-loops
is enabled, and not in other cases.
Thanks in advance, any additional insights on this matter would be greatly appreciated!