4

When trying to test the speed of functions, I found that not all parts of my code work in Release mode. The same code works perfectly in Debug mode, though.

I'm using VC++ compiler with /O2 optimization.

Here's the cut out part, which doesn't work.

int main()
{
    boost::timer::auto_cpu_timer t;

    for(int i = 0; i < 1000000; i++)
        gcdb(i, 5);
    return 0;
}

The generated assembly in release mode, the code for the for loop is missing only in this mode.

int main()
{
000000013F8E1280  sub         rsp,88h  
000000013F8E1287  mov         rax,qword ptr [__security_cookie (013F8E7150h)]  
000000013F8E128E  xor         rax,rsp  
000000013F8E1291  mov         qword ptr [rsp+70h],rax  
    boost::timer::auto_cpu_timer t;
000000013F8E1296  lea         rcx,[t]  
000000013F8E129B  mov         edx,6  
000000013F8E12A0  call        boost::timer::auto_cpu_timer::auto_cpu_timer (013F8E2DA0h)  

    for(int i = 0; i < 1000000; i++)
        gcdb(i, 5);
    return 0;
000000013F8E12A5  lea         rcx,[t]  
000000013F8E12AA  call        boost::timer::auto_cpu_timer::~auto_cpu_timer (013F8E2810h)  
000000013F8E12AF  xor         eax,eax  
}

gcdb() is just a function for the finding the GCD of two numbers.

What could be causing this code skipping?

Mysticial
  • 464,885
  • 45
  • 335
  • 332
SiimKallas
  • 934
  • 11
  • 23

2 Answers2

8

What you're seeing here is a compiler optimization known as Dead Code Elimination.

When the compiler sees that the result of some code is not needed, it is free to eliminate it. This is a standard optimization employed by all modern compilers.

A work-around to keep the compiler from optimizing it out is to actually use the output in some way:

int main()
{
    boost::timer::auto_cpu_timer t;

    int sum = 0;

    for(int i = 0; i < 1000000; i++)
        sum += gcdb(i, 5);

    cout << sum << endl;
    return 0;
}

Related: How does GCC optimize out an unused variable incremented inside a loop?

Community
  • 1
  • 1
Mysticial
  • 464,885
  • 45
  • 335
  • 332
  • 2
    @Ynau: The compiler is detecting that `gcdb` has no side effect, so it can be removed without altering the functionality of the program; similarly, the `for` loop can be removed. That's the purpose of optimisation: to improve the performance without altering the functionality. – MRAB Jan 27 '12 at 17:25
  • Could you also run in debug mode, but perform debug without debugging? – Jeremy Trifilo Jan 22 '13 at 04:15
  • @JeremyTrifilo You could, but the numbers you get will be meaningless. Benchmarking a program without enabling optimizations is like timing Usain Bolt's 100m dash without telling him he's actually supposed to run. – Mysticial Jan 22 '13 at 04:18
2

If the compiler can prove there are no side-effects and you don't use the result anywhere, it's free to prune that loop entirely.

Try summing the results and then returning the integer sum from main - that way there's an observable side-effect which should stop the optimizer getting too clever.

Useless
  • 64,155
  • 6
  • 88
  • 132