I'm writing a C program and want a loop unrolled. I need to force the compiler to unroll a loop where the number of iterations is known at compile time.
I've tried compiling using "-O0 -funroll-all-loops". I've tried using #pragma GCC unroll, I've tried using attribute((optimize("unroll-loops"))). None of it seems to unroll the following test function:
#define STR_LEN 12
int __attribute__((noinline)) func(char *input_str) {
char* fixed_str = "fixed string";
for (int i = 0; i < STR_LEN; i++) {
if (fixed_str[i] != input_str[i]) {
return -1;
}
if (i == STR_LEN - 1) {
return 0;
}
}
return 0;
}
I've compiled using "-S" to see the assembly code and the loop seems the same.
Edit: I used #pragma unroll and compiled with -O1 and it works.
As you have been indicated in the comments, you are meshing with the compilation options. But you can never enforce loop unrolling (or any other optimization on some code) if the compiler decides that the loop is not possible to unroll. Your loop seems to be unrollable, but the requirement that the unrolled loop must behave externally (as the user sees it) as it does without the optimization applies, can enforce the code to be conserved as a loop.
BTW, you can try to unroll it yourself. Let's see what happens:
iloop control variable. I'll substitute also the value ofSTR_LEN - 1constant expression so the ifs can be clearly eliminated in the next optimization pass. This is something we can do, because theivariable is not modified inside the loop (think that, just passing it by non-const *reference to a function would allow it to be modified inside the function and automatically blocked us to do this step, or even just declaring it asvolatile)if (i == STR_LEN -1)statements that result in afalseresult, as there's noelsepart in theifstatement.if (11 == 11)test is not necessary, as it results in the same code executed (return 0;) as if it has not been there from the beginning.||expression, based on the fact that all of them result in the same code executed (return -1) when the expression avaluates to atrueresult.fixed_stris a constant string.and probably you could reduce the test to just three tests with integers, if you realize that you can make the
||expression into a&&by negating it:inlinethis function, as it has become so simple that the call/return overhead becomes significative.