JIT .Net编译器错误?

Jan*_*Jan 22 .net c# jit visual-studio-2010

以下代码的结果不同如果它在后台启动调试器或没有调试器.如果开启优化,那么差异就在那里.

这是结果:

- >与优化:1000 2008 3016 1001 2009 3007 ...

- >无优化(如预期)1000 1008 1016 1001 1009 1017 ...

码:

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;

namespace OptimizerTest
{   
    public class Test
    {
        int dummy;

        public void TestFunction(int stepWidth)
        // stepWidth must be a parameter
        {
            for (int step = 0; step < stepWidth; step++)
            {
                dummy = step + 1000;
                // addition with constant ( same value as later !)
                for (int x = 0; x < 20; x += stepWidth)
                {
                    int index = x + 1000 + step;
                    // constant must be same as above and ?!?! 
                    // int index = x + step + 1000; works !!!!!
                    Console.Write("\n\r" + index);
                }
            }
        }

        [MethodImpl(MethodImplOptions.NoOptimization)]
        public void TestFunctionNoOptimization(int stepWidth)
        {
            for (int step = 0; step < stepWidth; step++)
            {
                dummy = step + 1000;
                for (int x = 0; x < 20; x += stepWidth)
                {
                    int index = x + 1000 + step;                        
                    Console.Write("\n\r" + index);
                }
            }
        }
    }

    class Program
    {
        /// <summary>
        /// Result differs from Start with F5 to Ctrl-F5
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Test test = new Test();
            Console.Write("\n\r---------\n\roptimized result\n\r-------------" );
            test.TestFunction(8);
            Console.Write("\n\r---------\n\rnot optimized result\n\r-------------");
            test.TestFunctionNoOptimization(8);
            Console.Write("\n\r---------\n\rpress any key");
            Console.ReadKey();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

错误的行为取决于内循环的迭代次数(x <5一切正常).非常有趣的是,当我使用时不会发生

   int index = x + step + 1000; 
Run Code Online (Sandbox Code Playgroud)

代替

   int index = x + 1000 + step; 
Run Code Online (Sandbox Code Playgroud)

我正在使用Visual Studio 2010 SP1并尝试使用.NET Framework从2.0到4.0.3.我总是看到同样的结果.

有人知道这个bug还是可以重现?

Han*_*ant 20

是的,这绝对是一个抖动优化器错误.其他SO用户重现它的原因是因为只有x64抖动似乎有这个bug.您必须将项目的平台目标设置为AnyCPU,在VS2012及更高版本上取消选中"首选32位"选项.

我没有仔细研究潜在的原因,但似乎在试图消除共同的step + 1000子表达时摸索.子表达式消除是标准抖动优化之一.但是它错误地将表达式代码合并到循环中,而不是像写入的那样将它保持在循环之外.例如,当您写下时,您会看到错误消失:

  dummy = step + 999;
Run Code Online (Sandbox Code Playgroud)

最新的.NET 4.5.1版本(我的机器上的clrjit.dll,v4.0.30319.34003)中仍然存在此错误,也存在于v2抖动(我机器上的mscorjit.dll,v2.0.50727.7905)中.

代码有点过于合成,无法推荐一个可靠的解决方法,你已经找到了一个,所以你可以继续驾驶你的项目.一般来说,我建议您自己删除子表达式:

  int index = x + dummy;  
Run Code Online (Sandbox Code Playgroud)

应该向Microsoft报告,您可以通过在connect.microsoft.com上发布错误报告来实现.如果你不想花时间让我知道,我会照顾它.

  • 提交为[反馈项目812093](https://connect.microsoft.com/VisualStudio/feedback/details/812093/x64-jitter-sub-expression-elimination-optimizer-bug). (7认同)