VS2010 C++ compiler generates incorrect code in full optimise /Ox /Ob1 - by GP Smith

Status : 

  Fixed<br /><br />
		This item has been fixed in the current or upcoming version of this product.<br /><br />
		A more detailed explanation for the resolution of this particular item may have been provided in the comments section.

Sign in
to vote
ID 715034 Comments
Status Closed Workarounds
Type Bug Repros 0
Opened 12/21/2011 8:45:31 AM
Access Restriction Public


I have attached a small native C++ project with a function that passes a double to a function. The first time, the value is passed correctly, the second time (after some intermediate code that does not change the double and does not use undefined values), the value is passed as -1#IND

The bug occurs in Win32 Release builds with full optimisation on. Changing the stack option does not seem to affect it. x64 builds do not show a problem.
Sign in to post a comment.
Posted by Microsoft on 12/27/2011 at 1:14 PM
Thank you for your response. The reason the issue has been marked "fixed" is that the issue has been fixed in the compiler. I realize that this has no immediate impact on the issue that you face with silent bad code generation, but there is only limited support I can provide via the Microsoft Connect forums. If you feel you need a fix to the VS2010 compiler in order to ship your product you may contact our support team and they may be able to provide you with additional help (for example getting a patch issued for this code generation problem).

In response to your queries regarding future releases: I’m not able to comment on release dates that aren’t yet publicly available. However, the fix for the bad FILD instruction is available in the currently released developer preview of Visual Studio 11 (available here: http://www.microsoft.com/download/en/details.aspx?id=27543).

Because this bug is very specific to the FILD instruction, it should be possible to work-around and/or detect this issue in a fairly straightforward manner on your end. For example, FILD converts an integer to a floating point value, so writing a function that does this and marking it __declspec(noinline) and using it instead of a direct cast will work-around the issue. As a far as detecting the bug writing a script to parse the generated listing files and looking for FILD x, where x is a register should quickly spot any additional instance of this in your code.

ian Bearman
VC++ Code Generation and Optimization Team
Posted by GP Smith on 12/23/2011 at 2:09 AM
Hi Ian,

Thanks for confirming the bug and taking the time to explain what went wrong. It feels a long time since I had to worry about optimisation causing bad code generation in a MS compiler.

However, having just got our company to upgrade the development team from VS2005 to VS2010 and having migrated our MFC, native, large, commercial application (where we found this problem) to the new system, must I now say that either we continue with 2005 or risk shipping code generated by a compiler with a known bug, or ship a product with optimisation disabled? When will the "next major compiler version" be released? Do you mean vNext?

Your suggestion of using SSE2 is not possible. We write code for use in the real world and have no control over which machines our customers choose to run code on.

In the particular instance of our application we have worked around the bug by forcing the double to be recalculated. My concern is that code that loads a fp value and gets a register pointer to it, then does something else, then uses it again and then the compiler backend notices that it has a register pointing at it cannot be that rare. The problem is made worse because the error is SILENT and in our case, only showed up in our test suite when the result of a complex calculation was incorrect... or is my code fragment sufficiently "unique" that this is unlikely?

I guess the word "Fixed" is from your point of view, rather than from mine!
Posted by Microsoft on 12/22/2011 at 12:17 PM
Thanks for reporting this. I can confirm the incorrect program execution with the optimization settings you specified. I was able to trace the problem to the compiler emitting an illegal instruction in the constructor for CVPwrBand. The instruction in question is "FILD ECX". The x87 FILD instruction doesn't take a register source, it always reads from memory. This bad instruction is corrupting the program.

You can avoid this problem by disabling optimizations for the function that contains the bad instruction or simply changing the source code slightly or optimization flags will change what the compiler emits and will most likely avoid this bad instruction. Another possible workaround is use the -arch:SSE2 flag. This flag will enable SSE2 instructions (not available on older hardware) and the compiler will favor using instructions from this instruction set for floating point over the older x87 instructions. This will avoid generation of the FILD instruction entirely. I recommend this solution if you are okay with dropping support for older processors that don’t support SSE2.

The next major compiler version will contain a fix for this problem.

ian Bearman
VC++ Code Generation and Optimization Team
Posted by MS-Moderator10 [Feedback Moderator] on 12/21/2011 at 9:12 PM
Thank you for submitting feedback on Visual Studio 2010 and .NET Framework. Your issue has been routed to the appropriate VS development team for investigation. We will contact you if we require any additional information.
Posted by MS-Moderator01 on 12/21/2011 at 9:45 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)