Skip to content

Commit

Permalink
JIT: block some struct promotion for OSR (dotnet#67131)
Browse files Browse the repository at this point in the history
This undoes part of dotnet#65903. OSR methods can't rely solely on their own analysis
for struct promotion as they only see parts of methods.
  • Loading branch information
AndyAyersMS authored Mar 25, 2022
1 parent 938f2e3 commit 6627183
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/coreclr/jit/lclvars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1851,6 +1851,14 @@ bool Compiler::StructPromotionHelper::CanPromoteStructVar(unsigned lclNum)
return false;
}

// If the local was exposed at Tier0, we currently have to assume it's aliased for OSR.
//
if (compiler->lvaIsOSRLocal(lclNum) && compiler->info.compPatchpointInfo->IsExposed(lclNum))
{
JITDUMP(" struct promotion of V%02u is disabled because it is an exposed OSR local\n", lclNum);
return false;
}

CORINFO_CLASS_HANDLE typeHnd = varDsc->GetStructHnd();
assert(typeHnd != NO_CLASS_HANDLE);

Expand Down
73 changes: 73 additions & 0 deletions src/tests/JIT/opt/OSR/invalidpromotion.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// 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;
using System.Runtime.InteropServices;

interface IFoo
{
public Span<object> AsSpan();
}

public struct ObjectSequence1 : IFoo
{
public object Value1;

public Span<object> AsSpan()
{
return MemoryMarshal.CreateSpan(ref Value1, 1);
}
}

public struct ObjectSequenceMany : IFoo
{
public object[] _values;

public Span<object> AsSpan()
{
return _values.AsSpan();
}

public ObjectSequenceMany(object[] x)
{
_values = x;
}
}

public class InvalidPromotion
{
[MethodImpl(MethodImplOptions.NoInlining)]
static bool G<T>(int n) where T : IFoo
{
// OSR cannot safely promote values
T values = default;

if (values is ObjectSequenceMany)
{
values = (T)(object)new ObjectSequenceMany(new object[5]);
}

Span<object> indexedValues = values.AsSpan();

// For a patchpoint here.
for (int i = 0; i < n; i++)
{
indexedValues[i] = "foo";
}

if (values is ObjectSequence1)
{
return (indexedValues[0] == ((ObjectSequence1)(object)values).Value1);
}

return false;
}

public static int Main()
{
return G<ObjectSequence1>(1) ? 100 : -1;
}
}


30 changes: 30 additions & 0 deletions src/tests/JIT/opt/OSR/invalidpromotion.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<DebugType />
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
<PropertyGroup>
<CLRTestBatchPreCommands><![CDATA[
$(CLRTestBatchPreCommands)
set COMPlus_TieredCompilation=1
set COMPlus_TC_QuickJitForLoops=1
set COMPlus_TC_OnStackReplacement=1
set COMPlus_OSR_HitLimit=1
set COMPlus_TC_OnStackReplacement=1
set COMPlus_TC_OnStackReplacement_InitialCounter=1
]]></CLRTestBatchPreCommands>
<BashCLRTestPreCommands><![CDATA[
$(BashCLRTestPreCommands)
export COMPlus_TieredCompilation=1
export COMPlus_TC_QuickJitForLoops=1
export COMPlus_TC_OnStackReplacement=1
export COMPlus_OSR_HitLimit=1
export COMPlus_TC_OnStackReplacement=1
export COMPlus_TC_OnStackReplacement_InitialCounter=1
]]></BashCLRTestPreCommands>
</PropertyGroup>
</Project>

0 comments on commit 6627183

Please sign in to comment.