Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiler optimization causing program to run slower

I have the following piece of code that I wrote in C. Its fairly simple as it just right bit-shifts x for every loop of for.

int main() {
   int x = 1;
   for (int i = 0; i > -2; i++) {
      x >> 2;
   }
}

Now the strange thing that is happening is that when I just compile it without any optimizations or with first level optimization (-O), it runs just fine (I am timing the executable and its about 1.4s with -O and 5.4s without any optimizations.

Now when I add -O2 or -O3 switch for compilation and time the resulting executable, it doesn't stop (I have tested for up to 60s).

Any ideas on what might be causing this?

like image 737
mmtauqir Avatar asked Aug 19 '11 15:08

mmtauqir


People also ask

Does code optimization improve compilation time?

Optimization should increase the speed and performance of the program. The compilation time must be kept reasonable. The optimization process should not delay the overall compiling process.

What is the role of optimizing the compiler?

In computing, an optimizing compiler is a compiler that tries to minimize or maximize some attributes of an executable computer program. Common requirements are to minimize a program's execution time, memory footprint, storage size, and power consumption (the last three being popular for portable computers).

How do I disable compiler optimization?

Use the command-line option -O0 (-[capital o][zero]) to disable optimization, and -S to get assembly file. Look here to see more gcc command-line options. Save this answer.


2 Answers

The optimized loop is producing an infinite loop which is a result of you depending on signed integer overflow. Signed integer overflow is undefined behavior in C and should not be depended on. Not only can it confuse developers it may also be optimized out by the compiler.

Assembly (no optimizations): gcc -std=c99 -S -O0 main.c

_main:
LFB2:
    pushq   %rbp
LCFI0:
    movq    %rsp, %rbp
LCFI1:
    movl    $1, -4(%rbp)
    movl    $0, -8(%rbp)
    jmp L2
L3:
    incl    -8(%rbp)
L2:
    cmpl    $-2, -8(%rbp)
    jg  L3
    movl    $0, %eax
    leave
    ret


Assembly (optimized level 3): gcc -std=c99 -S -O3 main.c

_main:
LFB2:
    pushq   %rbp
LCFI0:
    movq    %rsp, %rbp
LCFI1:
L2:
    jmp L2  #<- infinite loop
like image 178
Joe Avatar answered Oct 29 '22 20:10

Joe


You will get the definitive answer by looking at the binary that's produced (using objdump or something).

But as others have noted, this is probably because you're relying on undefined behaviour. One possible explanation is that the compiler is free to assume that i will never be less than -2, and so will eliminate the conditional entirely, and convert this into an infinite loop.

Also, your code has no observable side effects, so the compiler is also free to optimise the entire program away to nothing, if it likes.

like image 37
Oliver Charlesworth Avatar answered Oct 29 '22 20:10

Oliver Charlesworth