Don't eliminate a cpblk when offsets are different
authorCarol Eidt <carol.eidt@microsoft.com>
Fri, 11 May 2018 21:08:30 +0000 (14:08 -0700)
committerCarol Eidt <carol.eidt@microsoft.com>
Fri, 11 May 2018 21:08:30 +0000 (14:08 -0700)
When `fgMorphCopyBlock()` encounters a cpblk between two different offsets of the same local, if both fields are not recognizable to the JIT (i.e. the FieldSeqNode returned by IsLocalAddrExpr() and/or the gtFieldSeq field of a GT_LCL_FLD is FieldSeqStore::NotAField()), they should not be considered equal (and therefore should not be morphed to a `GT_NOP`).

Fixes #17969

src/jit/morph.cpp
tests/src/JIT/Regression/JitBlue/GitHub_17969/GitHub_17969.il [new file with mode: 0644]
tests/src/JIT/Regression/JitBlue/GitHub_17969/GitHub_17969.ilproj [new file with mode: 0644]

index 5313ac1..8fe6372 100644 (file)
@@ -10751,7 +10751,8 @@ GenTree* Compiler::fgMorphCopyBlock(GenTree* tree)
         bool srcSingleLclVarAsg  = false;
         bool destSingleLclVarAsg = false;
 
-        if ((destLclVar != nullptr) && (srcLclVar == destLclVar) && (destFldSeq == srcFldSeq))
+        if ((destLclVar != nullptr) && (srcLclVar == destLclVar) && (destFldSeq == srcFldSeq) &&
+            destFldSeq != FieldSeqStore::NotAField())
         {
             // Self-assign; no effect.
             GenTree* nop = gtNewNothingNode();
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_17969/GitHub_17969.il b/tests/src/JIT/Regression/JitBlue/GitHub_17969/GitHub_17969.il
new file mode 100644 (file)
index 0000000..bd49170
--- /dev/null
@@ -0,0 +1,154 @@
+// 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.
+
+.assembly extern mscorlib { auto }
+.assembly extern System.Console {auto}
+.assembly CpBlkBug { }
+
+.class private sequential ansi sealed MyStruct
+       extends [mscorlib]System.ValueType
+{
+  .pack 0
+  .size 84
+}
+
+.class private sequential ansi sealed MyArray1
+       extends [mscorlib]System.ValueType
+{
+  .pack 0
+  .size 160
+}
+
+.class private sequential ansi sealed MyArray2
+       extends [mscorlib]System.ValueType
+{
+  .pack 0
+  .size 1680
+}
+
+.class private auto ansi beforefieldinit Test
+       extends [mscorlib]System.Object
+{
+    .method assembly static unmanagedexp int32
+            main() cil managed
+    {
+        .entrypoint
+      .vtentry 11 : 1
+      // Code size       131 (0x83)
+      .maxstack  4
+      .locals ([0] int32 i,
+               [1] int32 j,
+               [2] valuetype MyStruct s2,
+               [3] valuetype MyArray2 s4,
+               [4] int32     returnVal)
+
+        // returnVal = 100;
+        ldc.i4.s   100
+        stloc      returnVal
+
+        // i = 10;
+        ldc.i4.s   10
+        stloc.0
+
+        // j = 6;
+        ldc.i4.6
+        stloc.1
+
+        // s4[j].a2 = 16;
+        ldloca.s   s4
+        ldloc      j
+        conv.i8
+        ldc.i4.s   84
+        conv.i8
+        mul
+        add
+        ldc.i4.s   80
+        conv.i8
+        add
+        ldc.i4.s   16
+        stind.i4
+
+        // s4[i] = s4[j];
+        ldloca.s   s4
+        ldloc      i
+        conv.i8
+        ldc.i4.s   84
+        conv.i8
+        mul
+        add
+        ldloca.s   s4
+        ldloc      j
+        conv.i8
+        ldc.i4.s   84
+        conv.i8
+        mul
+        add
+        ldc.i4.s   84
+        unaligned. 4
+        cpblk
+
+        // s2 = s4[i];
+        ldloca.s   s2
+        ldloca.s   s4
+        ldloc      i
+        conv.i8
+        ldc.i4.s   84
+        conv.i8
+        mul
+        add
+        ldc.i4.s   84
+        unaligned. 4
+        cpblk
+
+        // if (s4[i].a2 != 16) goto F1
+        ldloca.s   s4
+        ldloc      i
+        conv.i8
+        ldc.i4.s   84
+        conv.i8
+        mul
+        add
+        ldc.i4.s   80
+        conv.i8
+        add
+        ldind.i4
+        ldc.i4.s   16
+        beq.s      L2
+    
+    F1:
+        // Console.WriteLine("FAIL");
+        ldstr "FAIL"
+        call void [System.Console]System.Console::WriteLine(string)
+        // returnVal = -1;
+        ldc.i4.m1
+        stloc      returnVal
+    
+    L2:
+        // if (s2.a2 != 16) goto F2
+        ldloca.s   s2
+        ldc.i4.s   80
+        add
+        ldind.i4
+        ldc.i4.s   16
+        beq.s      L3
+    
+    F2:
+        // Console.WriteLine("FAIL");
+        ldstr "FAIL"
+        call void [System.Console]System.Console::WriteLine(string)
+        // returnVal = -1;
+        ldc.i4.m1
+        stloc      returnVal
+        br         L4
+
+    L3:
+        // Console.WriteLine("PASS");
+        ldstr "PASS"
+        call void [System.Console]System.Console::WriteLine(string)
+
+    L4:
+        ldloc     returnVal
+        ret
+    }
+}
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_17969/GitHub_17969.ilproj b/tests/src/JIT/Regression/JitBlue/GitHub_17969/GitHub_17969.ilproj
new file mode 100644 (file)
index 0000000..5934cf6
--- /dev/null
@@ -0,0 +1,23 @@
+<?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>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "></PropertyGroup>
+  <PropertyGroup>
+    <DebugType>None</DebugType>
+    <Optimize>True</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildProjectName).il" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>