Home Dashboard Directory Help
Search

Compiler Bug in Optimize Release Mode 64bit. by NorbertLindow


Status: 

Closed
 as Fixed Help for as Fixed


2
0
Sign in
to vote
Type: Bug
ID: 731193
Opened: 3/14/2012 9:40:17 AM
Access Restriction: Public
Moderator Decision: Sent to Engineering Team for consideration
0
Workaround(s)
view
1
User(s) can reproduce this bug

Description

I wrote a program with an own array class and got an unexpected behaviour.
I reduced the code as much as I can too keep this bug. Note that the program
makes no sense, but it should run completely.

The problem occurs with full optimization in release mode for 64bit under VS 2008 and VS 2010.

You find the complete source code in "steps to reproduce". The program exits
in the index operator method of the array class during an out of domain test.
This should not happen. I looked at the assembler code, which seems to be
wrong.

I am not completely sure that this is a compiler bug, but several other people looked
at it and had no further idea for a programer mistake.
Details
Sign in to post a comment.
Posted by Microsoft on 4/13/2012 at 1:54 PM
Hi Norbert, let me explain what's going on behind the scenes with the compiler here. This is a small standalone C example that exhibits the same problem as in your code:

#include <stdio.h>

int main() {
    for (int i = 0; i < 38; i++) {
        if (((i < 4) ? 0 : i * 16) > 600) { // a.k.a. if (LHS < 600) {
            printf("failure!\n");
        }
    }

    return 0;
}

The compiler is trying to optimize the comparison inside the loop by using a "range analysis", aka knowing that 'i' ranges from 0 to 37 to optimize the loop body.

In this particular case, the minimum value of the LHS of the comparison (when i = 0, 1, 2, 3) is 0, and the maximum value of the LHS of the comparison (when i = 37) is 37*16 => 592. Since both the min and max are less than 600 (and the expression generating the LHS is monotonically non-decreasing) the optimizer knows that the print will never occur, so it is optimized away.

However, the bug in the compiler is when computing the possible ranges of the LHS, it ends up computing the maximum value of 'i' as 38, so the range of the LHS is from 0 to 608. The print is NOT optimized away. Subsequent optimizations end up being wrong, and the failure message is printed. Keep in mind that only certain values of the upper bound exhibit this problem... it's a little strange from the source code point of view, but that is the case. Also, the bug is only present when there are multiple range comparisons of the loop induction variable in the loop body.

My original recommendation for a workaround was to turn off inlining for a particular function in your code. The reason this helped is merely because the comparison (the LHS above) was in a function separate from the loop. More precisely, the bug can only occur if the comparison expression is in the same function (after inlining) as the loop itself. Furthermore, the bug only manifests with specific loop bounds, and with specific LHS & RHS that are difficult to characterize.

The best workaround is to turn off optimizations around the functions that you think exhibit the problem. There is a pragma for doing this:

#pragma optimize("", off)
void test() {
    ...
}
#pragma optimize("", on)

If you feel you would like a hotfix for VS9 or VS10, please visit the support site:

http://support.microsoft.com/common/international.aspx?RDPATH=dm;en-us;selectassist&target=assistance

Also keep in mind that VS11 already has this fixed.

Sorry for the long description! Hopefully this helps.
Eric - Visual C++ Team
Posted by NorbertLindow on 3/16/2012 at 8:35 AM
Hi, thanks for the fast response. Should I forbid all possible inline methods in loops? Because I have several thousand lines of code and I do not want to do this (also for performance reasons). Is the only way to solve this problem, to buy VS 11 or is there another solution? Currently I have only VS 9 and 10.

Norbert
Posted by Microsoft on 3/15/2012 at 11:05 AM
Hi, thanks for this bug report. This is a bug in the loop optimizer which has been fixed for VS 11. I double checked that this is fixed in the VS 11 Beta release.

If you need a workaround, you can mark "T& operator[](int index)" with __declspec(noinline).

Eric
Microsoft Visual C++
Posted by MS-Moderator07 [Feedback Moderator] on 3/14/2012 at 9:54 PM
Thanks for your feedback.

We are rerouting this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue.
Posted by MS-Moderator01 on 3/14/2012 at 10:52 AM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Sign in to post a workaround.
File Name Submitted By Submitted On File Size  
BugProgram.zip 3/14/2012 1.14 MB