From 0ef205d30e893ff3af0dce4933606871cfdd994c Mon Sep 17 00:00:00 2001 From: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com> Date: Tue, 4 Jan 2022 00:03:55 +0300 Subject: [PATCH] Do not create non-null assertions from location nodes (#62743) --- src/coreclr/jit/assertionprop.cpp | 26 ++++++++++++--- .../JitBlue/Runtime_13762/Runtime_13762.cs | 39 ++++++++++++++++++++++ .../JitBlue/Runtime_13762/Runtime_13762.csproj | 9 +++++ 3 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_13762/Runtime_13762.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_13762/Runtime_13762.csproj diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index b842e13..71d2dc6 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -2558,8 +2558,14 @@ void Compiler::optAssertionGen(GenTree* tree) switch (tree->gtOper) { case GT_ASG: + // An indirect store - we can create a non-null assertion. Note that we do not lose out + // on the dataflow assertions here as local propagation only deals with LCL_VAR LHSs. + if (tree->AsOp()->gtGetOp1()->OperIsIndir()) + { + assertionInfo = optCreateAssertion(tree->AsOp()->gtGetOp1()->AsIndir()->Addr(), nullptr, OAK_NOT_EQUAL); + } // VN takes care of non local assertions for assignments and data flow. - if (optLocalAssertionProp) + else if (optLocalAssertionProp) { assertionInfo = optCreateAssertion(tree->AsOp()->gtOp1, tree->AsOp()->gtOp2, OAK_EQUAL); } @@ -2573,16 +2579,26 @@ void Compiler::optAssertionGen(GenTree* tree) case GT_BLK: case GT_DYN_BLK: case GT_IND: - case GT_NULLCHECK: - // All indirections create non-null assertions - assertionInfo = optCreateAssertion(tree->AsIndir()->Addr(), nullptr, OAK_NOT_EQUAL); + // R-value indirections create non-null assertions, but not all indirections are R-values. + // Those under ADDR nodes or on the LHS of ASGs are "locations", and will not end up + // dereferencing their operands. We cannot reliably detect them here, however, and so + // will have to rely on the conservative approximation of the GTF_NO_CSE flag. + if (tree->CanCSE()) + { + assertionInfo = optCreateAssertion(tree->AsIndir()->Addr(), nullptr, OAK_NOT_EQUAL); + } break; case GT_ARR_LENGTH: - // An array length is an indirection (but doesn't derive from GenTreeIndir). + // An array length is an (always R-value) indirection (but doesn't derive from GenTreeIndir). assertionInfo = optCreateAssertion(tree->AsArrLen()->ArrRef(), nullptr, OAK_NOT_EQUAL); break; + case GT_NULLCHECK: + // Explicit null checks always create non-null assertions. + assertionInfo = optCreateAssertion(tree->AsIndir()->Addr(), nullptr, OAK_NOT_EQUAL); + break; + case GT_BOUNDS_CHECK: if (!optLocalAssertionProp) { diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_13762/Runtime_13762.cs b/src/tests/JIT/Regression/JitBlue/Runtime_13762/Runtime_13762.cs new file mode 100644 index 0000000..f02a9af --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_13762/Runtime_13762.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; + +public class Runtime_13762 +{ + public static int Main() + { + try + { + Problem(null); + } + catch (NullReferenceException) + { + return 100; + } + + return 101; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Problem(ClassWithField a) + { + a.Field = a.Call(ref a.Field); + } +} + +public class ClassWithField +{ + public int Field; + + [MethodImpl(MethodImplOptions.NoInlining)] + public int Call(ref int a) + { + throw new Exception("This should have been an NRE!"); + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_13762/Runtime_13762.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_13762/Runtime_13762.csproj new file mode 100644 index 0000000..f492aea --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_13762/Runtime_13762.csproj @@ -0,0 +1,9 @@ + + + Exe + True + + + + + \ No newline at end of file -- 2.7.4