【问题标题】:RyuJit producing incorrect resultsRyuJit 产生不正确的结果
【发布时间】:2015-10-12 18:21:05
【问题描述】:

在最近升级到 .net 4.6 后,我们发现了 RyuJit 产生错误结果的错误,我们现在可以通过在 app.config 中添加 useLegacyJit enabled="true" 来解决这个问题。

如何调试下面生成的机器码?

我在 VS 2015 RTM 中创建了一个新的控制台项目,设置为 Release,Any CPU,未选中 Prefer 32 bit,在连接和不连接调试器的情况下运行都会产生相同的结果。

using System;
using System.Runtime.CompilerServices;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Calculate());
            Console.WriteLine(Calculate());

            Console.ReadLine();
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static Value Calculate()
        {
            bool? _0 = (bool?)null;
            bool? _1 = (bool?)true;
            if (!Value.IsPresent<bool>(_1))
            {
                return default(Value);
            }

            bool? result = null;
            result = (_1.Value ? new bool?(false) : result);
            if (_0.HasValue && _0.Value)
            {
            }
            return new Value(result);
        }

        public struct Value
        {
            bool? _value;

            public Value(bool? value)
            {
                _value = value;
            }

            public static bool IsPresent<T>(bool? _)
            {
                return _.HasValue;
            }

            public override string ToString()
            {
                return _value.ToString();
            }
        }
    }
}

它应该产生: 错误的 假的

但它会产生: 真的 假的

例子的关键部分是

result = true ? false : result;

它应该总是返回 false,但是从输出中可以看出,它在第一次运行该方法时返回 True,而在第二次运行该方法时返回不同的答案。从 Calculate() 方法中删除更多行将导致它始终返回 True,但给出的示例是我可以重现的最接近我们实际生产场景的示例。

【问题讨论】:

  • 是的,这是一个内联优化错误。第一个内联的 Calculate() 指令错误。在我看来,优化器内部某处不应该存在!。当然,我们无法修复此错误,您可以在 connect.microsoft.com 上报告它。暂时搁置 MethodImplOptions.AggressiveInlining,这不太可能经过广泛测试。
  • 实际的生产代码没有 AggressiveInlining 属性,但这是我可以重现这个小示例中的行为的唯一方法。生产代码是部分机器生成的,这就是示例代码看起来有点奇怪的原因。我刚刚在connect.microsoft.com/VisualStudio/feedback/details/1578173 报告了它
  • @BrandonAGr 这个错误是内联时引起的?使用MethodImplOptions.NoInlining 是否可行?
  • 我已经向 coreclr repo 报告了这个错误:github.com/dotnet/coreclr/issues/1299 在这个问题中,您可以找到带有 asm 列表的代码的简化版本。

标签: c# jit c#-6.0 .net-4.6 ryujit


【解决方案1】:

感谢您提供独立的重现程序,我可以确认这确实是优化器中的一个 RyuJIT 错误,由于内联而暴露。我已经对编译器进行了修复并确定了推出的详细信息。不要将 SO 变成错误跟踪器,而是为了更快地周转:ryujit@microsoft.com。

【讨论】:

  • 我已经构建了一个简化版的源代码,你可以在coreclr repo中找到它:github.com/dotnet/coreclr/issues/1299
  • @HansPassant 是的,这并不是一个错误报告,隐藏的问题是如何找到正在执行的机器代码。 Andrey 制作的简化示例使得在 Visual Studio 中查看反汇编变得非常容易,当然仍然不容易意识到哪些寄存器保存了哪些内容,但我能够浏览它
  • @schellap 此修复是否也修复了 - connect.microsoft.com/VisualStudio/Feedback/Details/1602437
猜你喜欢
  • 2020-12-14
  • 2015-01-06
  • 1970-01-01
  • 1970-01-01
  • 2017-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-22
相关资源
最近更新 更多