Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not create non-null assertions from location nodes #62743

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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)
{
Expand Down
39 changes: 39 additions & 0 deletions src/tests/JIT/Regression/JitBlue/Runtime_13762/Runtime_13762.cs
Original file line number Diff line number Diff line change
@@ -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!");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>