Visual Studio 2015 更新 3 - C++ 编译器错误?

问题描述 投票:0回答:2

我们观察到一个奇怪的情况,在 VS2015 Update3 中编译器会无缘无故地省略部分代码。

我们发现

  • 这种情况发生在 VS2015 Update3 中(帮助|关于说 14.0.25431.01 Update 3,cl.exe 版本 19.00.24215.1)
  • 这在 VS2015 Update2 中不会发生(帮助|关于说 14.0.25123.00 Update 2,cl.exe 版本 19.00.23918)
  • 仅当优化打开时才会发生这种情况(例如,在默认发布配置中)
  • x86 和 x64 中都会发生
  • 将代码片段插入全新的“Win32 控制台应用程序”时发生(我的意思是,不需要花哨的命令行选项)

我们设法将罪魁祸首代码最小化为以下片段:

#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>

int _tmain(int, _TCHAR*[])
{
    volatile int someVar = 1;

    const int indexOffset = someVar ? 0 : 1;    // Loop omitted
    // const int indexOffset = !someVar;        // Loop omitted
    // const int indexOffset = 0;               // Good
    // const int indexOffset = 1;               // Good
    // const int indexOffset = someVar;         // Good
    // const int indexOffset = someVar + 1;     // Good

    for (int i = 1 - indexOffset; i < 2 - indexOffset; ++i)
    {
        printf("Test passed\n");
    }

    return 0;
}

对于“省略循环”的行,编译器省略了整个循环体。为什么?据我所知,不存在未定义的行为。


第一个“循环省略”的反汇编:

int _tmain(int, _TCHAR*[])
{
01151010  push        ebp  
01151011  mov         ebp,esp  
01151013  push        ecx  
    volatile int someVar = 1;
01151014  mov         dword ptr [ebp-4],1  

    const int indexOffset = someVar ? 0 : 1;    // Loop omitted
0115101B  mov         eax,dword ptr [someVar]  
    // const int indexOffset = !someVar;        // Loop omitted
    // const int indexOffset = 0;               // Good
    // const int indexOffset = 1;               // Good
    // const int indexOffset = someVar;         // Good
    // const int indexOffset = someVar + 1;     // Good

    for (int i = 1 - indexOffset; i < 2 - indexOffset; ++i)
    {
        printf("Test passed\n");
    }

    system("pause");
0115101E  push        offset string "pause" (011520F8h)  
01151023  call        dword ptr [__imp__system (0115205Ch)]  
01151029  add         esp,4  
    return 0;
0115102C  xor         eax,eax  
}
0115102E  mov         esp,ebp  
01151030  pop         ebp  
01151031  ret

测试项目:http://dropmefiles.com/S7mwT


在线尝试!


错误报告:https://developercommunity.visualstudio.com/content/problem/71906/compiler-optimization-code- Generation-bug.html

c++ visual-studio-2015 compiler-errors compiler-optimization
2个回答
24
投票

是的,这是一个错误。具体来说,这是 VS2015 Update 3 中引入的新 SSA 优化器中的一个错误。未记录的命令行选项

-d2SSAOptimizer-
告诉编译器后端使用旧的优化器,这会导致该错误不明显

仅供参考,您可以将重现最小化为:

int main()
{
    volatile int someVar = 1;

    const int indexOffset = someVar ? 0 : 1;

    for (int i = 1 - indexOffset; i < 2 - indexOffset; ++i)
    {
        return 0;
    }
    return 1;
}

这将帮助编译器开发人员更快地定位问题。


Codeguard的补充(我决定Casey的答案应该是答案): 我收到了 Microsoft 的回复(Gratian Lup,博客文章介绍新的高级 Visual C++ 代码优化器的作者):

是的,这确实是 SSA 优化器本身的一个错误 - 通常是大多数 报告的新优化器中的错误存在于其他部分, 有时20年后现在会暴露出来。

它在一个小选项中。试图删除看起来像(a - Const1) CMP (a - Const2),如果没有溢出。问题是您的代码具有 (1 - indexOffset) CMP (2 - indexOffset) 和减法 当然,它是不可交换的 - 但优化器代码忽略了这一点 并像处理 (indexOffset - 1) 一样处理 (1 - indexOffset)。

此问题的修复将在下一个较大的更新中发布 VS2017。在那之前,禁用 SSA 优化器将是一个不错的选择 解决方法。仅禁用此功能的优化可能是 如果它不会太慢的话,这是更好的方法。这可以是 使用 #pragma optimize("", off) 完成:

https://msdn.microsoft.com/en-us/library/chh3fb0k.aspx


0
投票
聚会迟到了。我想知道这是否是您问题的修补程序?我

认为我看到了一个编译器错误,并且正在寻找 VS 2015 Update 3 编译器工具链的修补程序。

https://support.microsoft.com/en-us/topic/visual-c-optimizer-fixes-for-visual-studio-2015-update-3-2538b21a-f49c-37ec-b945-572c93dbb05b

© www.soinside.com 2019 - 2024. All rights reserved.