Home Dashboard Directory Help
Search

VC++ 11 compiler Bug in 64 bit application, optimization resulting in incorrect behaviour (shl) by PeterBaenziger


Status: 

Closed
 as Fixed Help for as Fixed


1
1
Sign in
to vote
Type: Bug
ID: 729108
Opened: 3/6/2012 7:39:16 AM
Access Restriction: Public
0
Workaround(s)
view
0
User(s) can reproduce this bug

Description

The following code executes wrong when using the default optimization settings on an I7-2670QM CPU, 64 bit Windows 8.

To reproduce, create a command line 64 bit c++ application with a single file main.cpp (not using precompiled header). main.cpp needs to contain the code pasted below, which is also attached as a screenshot. Set a breakpoint on the printf. Logically, the printf line can not be hit. Run the release version of the application in the debugger. The breakpoint will be hit, which is wrong.

The function "Fail" should return "false" for all integer input values other than zero. In the attached screenshot (Watch window and breakpoint) one can see that the function incorrectly returns 1 for the input value 32. It seems from the disassembler the expression "shl al,cl" sets "al" to 1 if "al" = 1 and "cl" = 32; altough I do not know why.

In Debug, the code works as expected. This is a serious defect as it means the compiler output does not match the compiled code, which can and will result in unexpected behaviour.

I have not attempted to reproduce this issue on different CPUs, or with 32 bit.

The program code:

bool Fail(size_t shift)
{
const size_t bitMap = 1;
if (shift < 64)
{
size_t mask = 1i64 << shift;
return (bitMap & mask) != 0;
}
else
return false;
}

int main(int argc, char** argv)
{
for (size_t i=1; i<33; i++)
{
if (Fail(i))
printf("compiler bug");
}
}


Edit:
The bug still occurs if the code is simplified as follows:

bool Fail(size_t shift)
{
    return (1 & (1i64 << shift)) != 0;
}
int main(int argc, char** argv)
{
    for (size_t i=1; i<33; i++)
        if (Fail(i))
            printf("compiler bug\n");
}
Details
Sign in to post a comment.
Posted by PeterBaenziger on 3/14/2012 at 1:24 AM
I stand corrected. Thank you.
Posted by Microsoft on 3/13/2012 at 10:57 AM
Keep in mind that shifting a 64-bit value by more than _63_ bits resuls in undefined behavior in C and C++. On Intel hardware the shift amount is mod'ed by the bit width of a the shift so a 64-bit shift will have its shift amount mod'ed by 64. This means that a 64-bit shift by 64 will result in a shift by 0, which is probably not what you want.

ian Bearman
VC++ Code Generation & Optimization
Posted by PeterBaenziger on 3/13/2012 at 5:29 AM
Thanks. Using #pragma optimize("", off) caused Fail(i) to fail at i = 64. We worked around the issue by refactoring the code to avoid the issue you described.
Posted by Microsoft on 3/7/2012 at 3:16 PM
Thanks for reporting this. This is definitely a compiler issue. I also believe this has been around for some time as I was able to reproduce the problem example on Visual Studio 2010 SP1 as well as Visual Studio 2012 Beta. The problem relates to using a 64-bit shift in an operation of smaller width. In this case using a 64-bit shift in a bool operation (byte width) results in the compiler incorrectly reducing the width of the shift.

I have a fix for this which is in testing now. I’m optimistic that the fix will be included in the final release of Visual Studio 2012.

In the meantime you can work around this limitation by disabling optimization around the function that exhibits the problem using #pragma optimize("", off). See MSDN for more details on how this pragma can be used.

Thanks,
ian Bearman
VC++ Code Generation & Optimization
Posted by Microsoft on 3/6/2012 at 5:39 PM
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  
SqmExtensionsLogs.zip (restricted) 3/6/2012 -
VsInfo.xml (restricted) 3/6/2012 -
DxDiagOutput.txt (restricted) 3/6/2012 -
ScreenShot.jpg (restricted) 3/6/2012 -