Compiler optimization causing program to run slower
Asked Answered
C

3

9

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?

Closefitting answered 19/8, 2011 at 15:41 Comment(16)
How is your loop supposed to stop when i will always be greater than -2Whipstitch
i is an int so -2 is actually INT_MAX -1 and notice the i > -2 instead of i < -2.Closefitting
Oh I see what you are doing then. I just wasn't sure if that was intentionalWhipstitch
Overflow is technically Undefined Behaviour, so anything may happen (regardless of optimizations setting).Aviv
Yeah instead of typing the maximum value of int - 1, I just did this :pClosefitting
@Aviv Yeah I know what you mean, but this should technically work...its C after all and this is the kind of stuff you do in C :DClosefitting
Actually pmg is right. And no, Undefined Behavior is not the thing you do in C. And "technically" it shouldn't workLiaison
@mtahmed: as you noticed, the result can be different for different optimization settings. It can also be different for different compilers on different architectures, or for different moon phases ... :)Aviv
@pmg: Curse those moon phases!Whipstitch
@mtahmed, does the same thing happen if you change the for condition so you don't have that UD?Eyestalk
I think that the agressive levels of optimizations are changing the loop in some whay (maybe by a while( true )). You should try to include the "volatile" modifier for "i" and "x" and see what happens. Also, the condition in the loop is a problem - you're relying on an overflow, and that's undefined behaviour, as @Aviv pointed out.Humph
@eran No I just tested with (int i = 0; i < INT_MAX - 1; i++) and its fine with that. So yeah compiler is making it an infinite loop.Closefitting
What exactly is x >> 2; supposed to achieve? You throw away the result, and it has no effect.Melar
Nothing...this is a purely educational question...Closefitting
Compiler was plain stupid here... I would have simply thrown the loop out and issued a warning that the entire loop had no effect.Thetisa
Relevant: usenix.org/conference/atc14/technical-sessions/presentation/…Eyeless
D
18

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
Dineric answered 19/8, 2011 at 15:55 Comment(2)
Out of curiosity, is the behavior of integer overflow undefined in C?Yiyid
@tskuzzy, signed integer overflow is UB. unsigned integers behave well and just wrap around. So OP's loop would work quite well when transposed to an unsigned setting.Solifidian
T
7

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.

Terror answered 19/8, 2011 at 15:54 Comment(0)
I
2

Additional information about why integer overflows are undefined can be found here:

http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html

Search for the paragraph "Signed integer overflow".

Inwrap answered 19/8, 2011 at 16:7 Comment(2)
There are also two more blogposts: blog.llvm.org/2011/05/… and blog.llvm.org/2011/05/…Inwrap
I really can't say enough how good those articles are. Among other things, the articles really made clear and concrete exactly why certain mysterious optimizations might remove code that appears to be necessary. The reasons for and consequences of UB are not very well understood in the C community, and those articles are about the best reading on the subject I can recall. Thanks again!Draftee

© 2022 - 2024 — McMap. All rights reserved.