fgRemoveEmptyBlocks();
- // Update type of return spill temp if we have gathered better info
- // when importing the inlinee.
+ // Update type of return spill temp if we have gathered
+ // better info when importing the inlinee, and the return
+ // spill temp is single def.
if (fgNeedReturnSpillTemp())
{
CORINFO_CLASS_HANDLE retExprClassHnd = impInlineInfo->retExprClassHnd;
if (retExprClassHnd != nullptr)
{
- lvaUpdateClass(lvaInlineeReturnSpillTemp, retExprClassHnd, impInlineInfo->retExprClassHndIsExact);
+ LclVarDsc* returnSpillVarDsc = lvaGetDesc(lvaInlineeReturnSpillTemp);
+
+ if (returnSpillVarDsc->lvSingleDef)
+ {
+ lvaUpdateClass(lvaInlineeReturnSpillTemp, retExprClassHnd,
+ impInlineInfo->retExprClassHndIsExact);
+ }
}
}
}
// out we can prove the method returns a more specific type.
if (info.compRetType == TYP_REF)
{
- lvaTable[lvaInlineeReturnSpillTemp].lvSingleDef = 1;
- JITDUMP("Marked V%02u as a single def temp\n", lvaInlineeReturnSpillTemp);
+ // The return spill temp is single def only if the method has a single return block.
+ if (retBlocks == 1)
+ {
+ lvaTable[lvaInlineeReturnSpillTemp].lvSingleDef = 1;
+ JITDUMP("Marked return spill temp V%02u as a single def temp\n", lvaInlineeReturnSpillTemp);
+ }
CORINFO_CLASS_HANDLE retClassHnd = impInlineInfo->inlineCandidateInfo->methInfo.args.retTypeClass;
if (retClassHnd != nullptr)
shouldUpdate = true;
}
- JITDUMP("\nlvaUpdateClass:%s Updating class for V%02u", shouldUpdate ? "" : " NOT", varNum);
- JITDUMP(" from(%p) %s%s", dspPtr(varDsc->lvClassHnd), info.compCompHnd->getClassName(varDsc->lvClassHnd),
- varDsc->lvClassIsExact ? " [exact]" : "");
- JITDUMP(" to(%p) %s%s\n", dspPtr(clsHnd), info.compCompHnd->getClassName(clsHnd), isExact ? " [exact]" : "");
+#if DEBUG
+ if (isNewClass || (isExact != varDsc->lvClassIsExact))
+ {
+ JITDUMP("\nlvaUpdateClass:%s Updating class for V%02u", shouldUpdate ? "" : " NOT", varNum);
+ JITDUMP(" from(%p) %s%s", dspPtr(varDsc->lvClassHnd), info.compCompHnd->getClassName(varDsc->lvClassHnd),
+ varDsc->lvClassIsExact ? " [exact]" : "");
+ JITDUMP(" to(%p) %s%s\n", dspPtr(clsHnd), info.compCompHnd->getClassName(clsHnd), isExact ? " [exact]" : "");
+ }
+#endif // DEBUG
if (shouldUpdate)
{
--- /dev/null
+// 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.Runtime.CompilerServices;
+
+class B
+{
+ public virtual int F() => 33;
+}
+
+sealed class D : B
+{
+ public override int F() => 44;
+}
+
+class X
+{
+ volatile static bool p;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static B GB() => new B();
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static D GD() => new D();
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static B G() => p ? GD() : GB();
+
+ public static int Main()
+ {
+ p = false;
+ // After inlining G(), the jit must not update
+ // the type of the return spill temp for G(), or it
+ // may incorrectly devirtualize the call to F()
+ return G().F() + 67;
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+ <OutputType>Exe</OutputType>
+ <DebugType></DebugType>
+ <Optimize>True</Optimize>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="$(MSBuildProjectName).cs" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>
\ No newline at end of file