I\'m currently experiencing random floating point errors when compiling for x86 targets using VC++ 11 (CTP Update 1). See the short example \"test.cpp\" bel
/GL
ignores default calling conventions, by design. With LTCG, the compiler/linker knows about the entire call graph so it can match caller and callee. Using an SSE register isn't weird in that context.
I'm not entirely sure what you mean by "get_scaling_factor()
pushes the result on the floating point stack", though. Do you mean that the compiler fails to inline it? I expect the compiler to do so, since the call graph has only one caller. (We know that `get_scaling_factor(targetUnits) was inlined, since that would have caused a division by zero otherwise)
If the compiler indeed fails to inline get_scaling_factor()
, then you've in fact found two bugs: One inlining failure, and one custom calling convention failure.
Yes, this is definitely a code optimizer bug and I had no trouble reproducing it. Optimizer bugs are usually associated with inlining but that's not the case here. This bug got introduced by the heavy code-gen changes in VS2012 that support the new auto-vectorizing feature.
In a nutshell, the get_scaling_factor() function returns the result on the FPU stack. The code generator properly emits the instruction to retrieve it from the stack and store it in an XMM register. But the optimizer inappropriate removes that code entirely, as though it assumes that the function result was already stored in XMM0.
A workaround is hard to come by, specializing the template function for double has no effect. Disabling optimization with #pragma optimize works:
#pragma optimize("", off)
__declspec(noinline)
double scale(double value, int units)
{
return scale<9>(value, units);
}
#pragma optimize("", on)
Your repro code is very good and Microsoft will have no trouble fixing this bug from this. You can file a feedback report at connect.microsoft.com, just link to this question. Or if you are in a hurry then you can contact Microsoft Support although I'd imagine they'll give you the same workaround to last you to the service pack.
UPDATE: fixed in VS2013.