Search code examples
cgcccompiler-optimizationbit-shift

Compiler optimization causing strange behavior with bit-wise shifts


Disclaimer, this is about shift overflows which I know gives undefined behavior; so this really shouldn't be a question. The reason I am asking this is for my curiosity.

Here is my code.

test.c:

#include <stdio.h>

void func(int val)
{
    int allOnes = 0xffffffff;

    printf("0x%x << 32  = 0x%x\n", allOnes, allOnes << 32);
    printf("0x%x << val = 0x%x\n", allOnes, allOnes << val);
}

int main()
{
    func(32);
}

When I run this with no compiler optimizations (gcc -O0 -Wall -g test.c -o test.o) I get the following.

0xffffffff << 32  = 0xffffffff
0xffffffff << val = 0xffffffff

However, when I run this with compiler optimizations (gcc -O1 -Wall -g test.c -o test.o) I get the following.

0xffffffff << 32  = 0x0
0xffffffff << val = 0xffffffff

My question is: what causes this?

EDIT: More specifically, why is there a discrepancy between running with compiler optimization and without?


Solution

  • I did some digging and I found when you use compiler optimizations (-O1), the compiler replaces the shift operation with its "result". In the assembly, there is a mov edx, 0 as opposed to a shl edx, 32.

    The discrepancy here is just due to the processor and the compiler having different results. It is undefined behavior after all.