Visual C ++ 2012(x86)中可能的编译器错误? [英] Possible compiler bug in Visual C++ 2012 (x86)?

查看:211
本文介绍了Visual C ++ 2012(x86)中可能的编译器错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用 VC ++ 11(CTP Update 1)编译x86目标时,我目前遇到随机浮点错误。请参见下面的简短示例test.cpp,并使用以下命令编译:

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" below, and compile using:

cl /GL /O2 /EHsc test.cpp /link /MACHINE:X86

输出应为 10 == 10 ,但是当 / GL (整个程序优化)被启用时,它产生 10 == 0 。问题似乎是 get_scaling_factor()推送浮点栈上的结果,但是调用函数在SSE寄存器中预期它 XMM0

The output should be 10 == 10, but it produces 10 == 0 when /GL (whole program optimization) is enabled. The problem seems to be that get_scaling_factor() pushes the result on the floating point stack, but the calling function is expecting it in the SSE register XMM0.

问题:我缺少明显的东西,或者这是一个错误?测试程序当然没有意义,因为它是一个测试用例。

Question: am I missing something obvious, or is this really a bug? The test program, of course, doesn't make sense, as it is a stripped down test case.

test.cpp: p>

test.cpp:

#include <iostream>

template <typename T>
inline T get_scaling_factor(int units)
{
    switch (units)
    {
    case 0: return 1;  
    case 1: return 10;  
    case 2: return 100;  
    case 3: return 1000;  
    case 4: return 10000;  
    case 5: return 100000;  
    case 6: return 1000000;  
    case 7: return 10000000;  
    case 8: return 100000000;  
    case 9: return 1000000000; 
    default: return 1;
    }
}

template <int targetUnits, typename T>
inline T scale(T value, int sourceUnits)
{
    return value   * get_scaling_factor<T>(sourceUnits) 
                   / get_scaling_factor<T>(targetUnits);
}

__declspec(noinline)
double scale(double value, int units) 
{
    return scale<9>(value, units);
}

int main()
{
    std::cout << "10 = " << scale(1e9, 1) << std::endl;
}






更新



问题由Microsoft确认。它甚至影响像这样的直接代码:


Update

Issue confirmed by Microsoft. It even affects straight forward code like this:

#include <stdio.h>
double test(int a)
{
    switch (a)
    {
    case 0: return 1.0;
    case 1: return 10.0;
    case 2: return 100.0;
    case 3: return 1000.0;
    case 4: return 10000.0;
    case 5: return 100000.0;
    case 6: return 1000000.0;
    case 7: return 10000000.0;
    case 8: return 100000000.0;
    case 9: return 1000000000.0;
    default: return 1.0;
    }
}

void main()
{
    int nine = 9;
    double x = test(nine);
    x /= test(7);
    int val = (int)x;
    if (val == 100)
        printf("pass");
    else 
        printf("fail, val is %d", val);
}


推荐答案

代码优化器bug和我没有麻烦重现它。优化程序错误通常与内联相关联,但这不是这里的情况。这个bug是由VS2012中支持新的自动矢量化特征的重代码变化引入的。

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.

简而言之,get_scaling_factor()函数返回FPU堆栈上的结果。代码生成器正确地发出指令以从堆栈中检索它并将其存储在XMM寄存器中。但是优化程序不适当地删除了该代码,因为它假设函数结果已经存储在XMM0中。

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.

一个解决方法很难实现,专门的模板函数对于double没有效果。使用#pragma optimize停用优化工作:

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)

是非常好的,微软将没有固定这个bug从这个问题。您可以在connect.microsoft.com提交反馈报告,只需链接到此问题。或者如果你很忙,那么你可以联系Microsoft支持,虽然我想象他们会给你相同的解决方法,让你的服务包。

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:在VS2013中修复。

UPDATE: fixed in VS2013.

这篇关于Visual C ++ 2012(x86)中可能的编译器错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆