3

Can a C compiler ever optimize a loop by running it?

For example:

int num[] = {1, 2, 3, 4, 5}, i;
for(i = 0; i < sizeof(num)/sizeof(num[0]); i++) {
  if(num[i] > 6) {
    printf("Error in data\n");
    exit(1);
  }
}

Instead of running this each time the program is executed, can the compiler simply run this and optimize it away?

3
  • 3
    Well, you can check with ex. gcc -S. This is called 'loop unrolling'; the compiler effectively copy+pastes the loop body, changing the i variable to a constant each time. AFAIK it works well for small loops, and can allow other optimizations to happen (such as eliminating the dead code that the if branch would generate). Commented Jul 14, 2015 at 23:08
  • Try compiling with -S -funroll-loops and check the output. "Running" the loop isn't quite the right term, though - it's not like the code is actually executed. Commented Jul 14, 2015 at 23:09
  • Look up 'profile-based optimization' or PBO (aka 'profile-guided optimization' or PGO). Yes, it is possible for optimizers to optimize based on the observed performance of the program running. See also 'link-time optimization' (LTO) and 'whole-program optimization'. Commented Jul 14, 2015 at 23:12

4 Answers 4

4

Let's have a look… (This really is the only way to tell.)

Fist, I've converted your snippet into something we can actually try to compile and run and saved it in a file named main.c.

#include <stdio.h>

static int
f()
{
  const int num[] = {1, 2, 3, 4, 5};
  int i;
  for (i = 0; i < sizeof(num) / sizeof(num[0]); i++)
    {
      if (num[i] > 6)
        {
          printf("Error in data\n");
          return 1;
        }
    }
  return 0;
}

int
main()
{
  return f();
}

Running gcc -S -O3 main.c produces the following assembly file (in main.s).

        .file   "main.c"
        .section        .text.unlikely,"ax",@progbits
.LCOLDB0:
        .section        .text.startup,"ax",@progbits
.LHOTB0:
        .p2align 4,,15
        .globl  main
        .type   main, @function
main:
.LFB22:
        .cfi_startproc
        xorl    %eax, %eax
        ret
        .cfi_endproc
.LFE22:
        .size   main, .-main
        .section        .text.unlikely
.LCOLDE0:
        .section        .text.startup
.LHOTE0:
        .ident  "GCC: (GNU) 5.1.0"
        .section        .note.GNU-stack,"",@progbits

Even if you don't know assembly, you'll notice that the string "Error in data\n" is not present in the file so, apparently, some kind of optimization must have taken place.

If we look closer at the machine instructions generated for the main function,

xorl    %eax, %eax
ret

We can see that all it does is XOR'ing the EAX register with itself (which always results in zero) and writing that value into EAX. Then it returns again. The EAX register is used to hold the return value. As we can see, the f function was completely optimized away.

Sign up to request clarification or add additional context in comments.

3 Comments

Interestingly, clang (tested on 3.5.1) can achieve this with a mere -O1.
So say you have a deterministic program that takes a long time to run (perhaps num is very long, yet compiled in). At what point does the compiler say "I'll optimize this now", vs "Let it run"?
@Ariel There is no reliable way to tell other than looking at the assembly code actually generated for your program and if you change a tiny bit, something different might happen. At least unless you know intimate details of your compiler. Have a look at this question and my answer there for an example how tricky it can become to reason about what optimization the compiler will ultimately decide to perform.
1

Yes. The C compiler unrolls loops automatically with options -O3 and -Otime.

7 Comments

I'm not sure why you need to unroll any loops here. All that's required is to notice that the code does nothing.
Isn't unrolling the loop part of the process that the compiler does to see that the code does nothing?
I don't see why. You can realize easily that the loop body is empty (since the condition is always false) without unrolling...
Yes, I can realise it, but I am not a compiler. How does the compiler realise it?
If even you can realize it, surely it's possible to program a machine to realize the same thing :-)
|
0

You didn't specify the compiler, but using gcc with -O3 and taking the size calculation outside the for maybe it could do a little adjustment.

Comments

0

Compilers can do even better than that. Not only can compilers examine the effect of running code "forward", but the Standard even allows them to work code logic in reverse in situations involving potential Undefined Behavior. For example, given:

#include <stdio.h>
int main(void)
{
  int ch = getchar();
  int q;
  if (ch == 'Z')
    q=5;
  printf("You typed %c and the magic value is %d", ch, q);
  return 0;
}

a compiler would be entitled to assume that the program will never receive any input which would cause the printf to be reached without q having received a value; since the only input character which would cause q to receive a value would be 'Z', a compiler could thus legitimately replace the code with:

int main(void)
{
  getchar();
  printf("You typed Z and the magic value is 5");
}

If the user types Z, the behavior of the original program will be well-defined, and the behavior of the latter will match it. If the user types anything else, the original program will invoke Undefined Behavior and, as a consequence, the Standard will impose no requirements on what the compiler may do. A compiler will be entitled to do anything it likes, including producing the same result as would be produced by typing Z.

4 Comments

But this doesn't really answer the OP's question.
What "second printf"? There's only one in each code snippet.
@ThePcLuddite: Is that a little better?
@void_ptr: Mea culpa. I simplified my example and neglected to fix the text to match.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.