From e78d2fd7a533c5244e442fdaec032ca697fc8a97 Mon Sep 17 00:00:00 2001 From: Eugene Rozenfeld Date: Tue, 20 Jun 2017 16:46:02 -0700 Subject: Fix for a bug in fgMorphRecognizeBoxNullable. fgMorphRecognizeBoxNullable doesn't work correctly when called during re-morphing. In particular it can't handle late args in the call to CORINFO_HELP_BOX_NULLABLE. The test case results in several asserts (the first one in lsra) followed by an infinite loop in the jit. The reason the optimization is not performed during global morph is that only patterns with GT_EQ and GT_NE are handled. Some versions of csc generate ... ldnull cgt.un ret for this C# line null != this.value so we get GT_GT instead. The fix has two parts: 1. Don't attempt to perform the optimization when called during re-morph and the struct parameter is a late arg. 2. Call fgMorphRecognizeBoxNullable for GT_GT nodes with GTF_UNSIGNED set. This allows the optimization to fire during global morph. --- .../JitBlue/GitHub_12392/GitHub_12392.cs | 108 +++++++++++++++++++++ .../JitBlue/GitHub_12392/GitHub_12392.csproj | 38 ++++++++ 2 files changed, 146 insertions(+) create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12392/GitHub_12392.cs create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12392/GitHub_12392.csproj (limited to 'tests/src') diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12392/GitHub_12392.cs b/tests/src/JIT/Regression/JitBlue/GitHub_12392/GitHub_12392.cs new file mode 100644 index 0000000000..23058fd768 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_12392/GitHub_12392.cs @@ -0,0 +1,108 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Reflection; + +namespace Test +{ + // This is a regression test for a bug in fgMorphRecognizeBoxNullable. + // See the comment in Setting.HasValue for details. + class Program + { + + static int Main(string[] args) + { + Test t = new Test(); + if (!t.TestMethod()) + { + Console.WriteLine("SUCCESS"); + return 100; + } + else + { + Console.WriteLine("FAILURE"); + return 0; + } + } + } + + class Test + { + Setting supportInteractive = Setting.ForBool(null); + + public bool TestMethod() + { + return this.supportInteractive.HasValue; + } + } + + public class Setting + { + Setting() + { + } + + public Setting(T value) + { + this.value = value; + } + + public bool HasValue + { + get + { + if (this.value != null) + { + Type t = this.value.GetType(); + if (t.IsGenericType) + { + if (t.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + PropertyInfo hasValueProperty = t.GetProperty("HasValue"); + bool result = (bool)hasValueProperty.GetValue(this.value, null); + return result; + } + } + } + + // The bug reproduces when the C# compiler generates + // ldnull + // cgt.un + // ret + // for this statement. + // The code above this statement is necessary so that some assertions are + // propagated and the statement gets re-morphed. + // The bug in fgMorphRecognizeBoxNullable was that it couldn't deal + // with a morphed helper call correctly. + return null != this.value; + } + } + + T value; + public T Value + { + get { return this.value; } + set { this.value = value; } + } + } + + public class Setting + { + Setting() + { + ; + } + + public static Setting ForBool(string parameter) + { + if (null == parameter) + { + return new Setting(null); + } + Setting setting = new Setting(bool.Parse(parameter)); + return setting; + } + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12392/GitHub_12392.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_12392/GitHub_12392.csproj new file mode 100644 index 0000000000..2cafa4cedf --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_12392/GitHub_12392.csproj @@ -0,0 +1,38 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + + + + + + + + + + False + + + + + True + + + + + + + + + + + -- cgit v1.2.3