int prefixFlags = 0;
bool explicitTailCall, constraintCall, readonlyCall;
- bool insertLdloc = false; // set by CEE_DUP and cleared by following store
typeInfo tiRetVal;
unsigned numArgs = info.compArgsCount;
if (op1->gtOper == GT_LCL_VAR && lclNum == op1->gtLclVarCommon.gtLclNum)
{
- if (insertLdloc)
- {
- // This is a sequence of (ldloc, dup, stloc). Can simplify
- // to (ldloc, stloc). Goto LDVAR to reconstruct the ldloc node.
- CLANG_FORMAT_COMMENT_ANCHOR;
-
-#ifdef DEBUG
- if (tiVerificationNeeded)
- {
- assert(
- typeInfo::AreEquivalent(tiRetVal, NormaliseForStack(lvaTable[lclNum].lvVerTypeInfo)));
- }
-#endif
-
- op1 = nullptr;
- insertLdloc = false;
-
- impLoadVar(lclNum, opcodeOffs + sz + 1);
- break;
- }
- else if (opts.compDbgCode)
+ if (opts.compDbgCode)
{
op1 = gtNewNothingNode();
goto SPILL_APPEND;
op1 = gtNewAssignNode(op2, op1);
}
- /* If insertLdloc is true, then we need to insert a ldloc following the
- stloc. This is done when converting a (dup, stloc) sequence into
- a (stloc, ldloc) sequence. */
-
- if (insertLdloc)
- {
- // From SPILL_APPEND
- impAppendTree(op1, (unsigned)CHECK_SPILL_ALL, impCurStmtOffs);
-
-#ifdef DEBUG
- // From DONE_APPEND
- impNoteLastILoffs();
-#endif
- op1 = nullptr;
- insertLdloc = false;
-
- impLoadVar(lclNum, opcodeOffs + sz + 1, tiRetVal);
- break;
- }
-
goto SPILL_APPEND;
case CEE_LDLOCA:
impStackTop(0);
}
- // Convert a (dup, stloc) sequence into a (stloc, ldloc) sequence in the following cases:
- // - If this is non-debug code - so that CSE will recognize the two as equal.
- // This helps eliminate a redundant bounds check in cases such as:
- // ariba[i+3] += some_value;
- // - If the top of the stack is a non-leaf that may be expensive to clone.
+ // If the expression to dup is simple, just clone it.
+ // Otherwise spill it to a temp, and reload the temp
+ // twice.
+ op1 = impPopStack(tiRetVal);
- if (codeAddr < codeEndp)
+ if (!opts.compDbgCode && !op1->IsIntegralConst(0) && !op1->IsFPZero() && !op1->IsLocal())
{
- OPCODE nextOpcode = (OPCODE)getU1LittleEndian(codeAddr);
- if (impIsAnySTLOC(nextOpcode))
- {
- if (!opts.compDbgCode)
- {
- insertLdloc = true;
- break;
- }
- GenTree* stackTop = impStackTop().val;
- if (!stackTop->IsIntegralConst(0) && !stackTop->IsFPZero() && !stackTop->IsLocal())
- {
- insertLdloc = true;
- break;
- }
- }
+ const unsigned tmpNum = lvaGrabTemp(true DEBUGARG("dup spill"));
+ impAssignTempGen(tmpNum, op1, tiRetVal.GetClassHandle(), (unsigned)CHECK_SPILL_ALL);
+ var_types type = genActualType(lvaTable[tmpNum].TypeGet());
+ op1 = gtNewLclvNode(tmpNum, type);
}
- /* Pull the top value from the stack */
- op1 = impPopStack(tiRetVal);
-
- /* Clone the value */
op1 = impCloneExpr(op1, &op2, tiRetVal.GetClassHandle(), (unsigned)CHECK_SPILL_ALL,
nullptr DEBUGARG("DUP instruction"));
- /* Either the tree started with no global effects, or impCloneExpr
- evaluated the tree to a temp and returned two copies of that
- temp. Either way, neither op1 nor op2 should have side effects.
- */
assert(!(op1->gtFlags & GTF_GLOB_EFFECT) && !(op2->gtFlags & GTF_GLOB_EFFECT));
-
- /* Push the tree/temp back on the stack */
impPushOnStack(op1, tiRetVal);
-
- /* Push the copy on the stack */
impPushOnStack(op2, tiRetVal);
break;
prevOpcode = opcode;
prefixFlags = 0;
- assert(!insertLdloc || opcode == CEE_DUP);
}
- assert(!insertLdloc);
-
return;
#undef _impResolveToken
}
--- /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;
+
+public class Base
+{
+ public int value;
+ public void B0() { value += 12; }
+ public virtual void B1() { value += 33; }
+}
+
+// Ensure that D1 and D2 have enough virtuals that the slot number for
+// the virtual M1 is greater than any virtual's slot number in B.
+
+public class D1 : Base
+{
+ public virtual void MA() { }
+ public virtual void MB() { }
+ public virtual void MC() { }
+ public virtual void MD() { }
+
+ public virtual void M1() { value += 44; }
+}
+
+public class D2 : Base
+{
+ public virtual void MA() { }
+ public virtual void MB() { }
+ public virtual void MC() { }
+ public virtual void MD() { }
+
+ public virtual void M1() { value += 55; }
+}
+
+// Aggressive use of 'dup' here by CSC will confuse the jit, and it
+// may substitute 'b' for uses of d1 and d2. This is not
+// value-incorrect but loses type information.
+//
+// This loss of type information subsequently triggers an assert in
+// devirtualzation because b does not have M1 as virtual method.
+
+public class Test
+{
+ public static int Main(string[] args)
+ {
+ Base b;
+
+ if (args.Length > 0)
+ {
+ D1 d1 = new D1();
+ b = d1;
+ d1.B1();
+ d1.M1();
+ }
+ else
+ {
+ D2 d2 = new D2();
+ b = d2;
+ d2.B1();
+ d2.M1();
+ }
+
+ b.B0();
+ return b.value;
+ }
+}
--- /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)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT .0\UITestExtensionPackages</ReferencePath>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ </PropertyGroup>
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+ <PropertyGroup>
+ <DebugType>None</DebugType>
+ <Optimize>True</Optimize>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="GitHub_9945.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <PropertyGroup>
+ <ProjectJson>$(JitPackagesConfigFileDirectory)minimal\project.json</ProjectJson>
+ <ProjectLockJson>$(JitPackagesConfigFileDirectory)minimal\project.lock.json</ProjectLockJson>
+ </PropertyGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+ </PropertyGroup>
+</Project>