Fix mismatched type IND(LCL_VAR_ADDR) folding in RewriteSIMDOperand (dotnet/coreclr...
authormikedn <onemihaid@hotmail.com>
Fri, 8 Nov 2019 23:21:49 +0000 (01:21 +0200)
committerCarol Eidt <carol.eidt@microsoft.com>
Fri, 8 Nov 2019 23:21:49 +0000 (15:21 -0800)
* Fix mismatched type IND(LCL_VAR_ADDR) folding in RewriteSIMDOperand

If the indirection and the variable have different SIMD types then a LCL_FLD node of the appropiate type is needed instead of a LCL_VAR node.

* Delete unused loadForm function

Commit migrated from https://github.com/dotnet/coreclr/commit/a0bbdf98efd5b96c041d8b49d2a61d0ce5bf3212

src/coreclr/src/jit/compiler.h
src/coreclr/src/jit/rationalize.cpp
src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_27405/GitHub_27405.cs [new file with mode: 0644]
src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_27405/GitHub_27405.csproj [new file with mode: 0644]

index 06451ab85ecd893d89f9e685fbb30f383a947018..2a4c5c8ba8235ed8ff5bf0ed71b363ccfa155dc0 100644 (file)
@@ -7768,27 +7768,6 @@ private:
         return isOpaqueSIMDType(varDsc->lvVerTypeInfo.GetClassHandle());
     }
 
-    // Returns true if the type of the tree is a byref of TYP_SIMD
-    bool isAddrOfSIMDType(GenTree* tree)
-    {
-        if (tree->TypeGet() == TYP_BYREF || tree->TypeGet() == TYP_I_IMPL)
-        {
-            switch (tree->OperGet())
-            {
-                case GT_ADDR:
-                    return varTypeIsSIMD(tree->gtGetOp1());
-
-                case GT_LCL_VAR_ADDR:
-                    return lvaTable[tree->AsLclVarCommon()->GetLclNum()].lvSIMDType;
-
-                default:
-                    return isSIMDTypeLocal(tree);
-            }
-        }
-
-        return false;
-    }
-
     static bool isRelOpSIMDIntrinsic(SIMDIntrinsicID intrinsicId)
     {
         return (intrinsicId == SIMDIntrinsicEqual || intrinsicId == SIMDIntrinsicLessThan ||
index 4293880e39291e9cbc9ad1f9006fb3e4229127b1..4c1f32c6f9284b53eda7070adc19029f361fb001 100644 (file)
@@ -37,21 +37,6 @@ genTreeOps addrForm(genTreeOps loadForm)
     }
 }
 
-// return op that is the load equivalent of the given addr opcode
-genTreeOps loadForm(genTreeOps addrForm)
-{
-    switch (addrForm)
-    {
-        case GT_LCL_VAR_ADDR:
-            return GT_LCL_VAR;
-        case GT_LCL_FLD_ADDR:
-            return GT_LCL_FLD;
-        default:
-            noway_assert(!"not a local address opcode\n");
-            unreached();
-    }
-}
-
 // copy the flags determined by mask from src to dst
 void copyFlags(GenTree* dst, GenTree* src, unsigned mask)
 {
@@ -93,14 +78,33 @@ void Rationalizer::RewriteSIMDOperand(LIR::Use& use, bool keepBlk)
         return;
     }
 
-    // If we have GT_IND(GT_LCL_VAR_ADDR) and the GT_LCL_VAR_ADDR is TYP_BYREF/TYP_I_IMPL,
-    // and the var is a SIMD type, replace the expression by GT_LCL_VAR.
+    // If we have GT_IND(GT_LCL_VAR_ADDR) and the var is a SIMD type,
+    // replace the expression by GT_LCL_VAR or GT_LCL_FLD.
     GenTree* addr = tree->AsIndir()->Addr();
-    if (addr->OperIsLocalAddr() && comp->isAddrOfSIMDType(addr))
+    if (addr->OperIs(GT_LCL_VAR_ADDR) && comp->lvaGetDesc(addr->AsLclVar())->lvSIMDType)
     {
         BlockRange().Remove(tree);
 
-        addr->SetOper(loadForm(addr->OperGet()));
+        var_types lclType = comp->lvaGetDesc(addr->AsLclVar())->TypeGet();
+
+        if (lclType == simdType)
+        {
+            addr->SetOper(GT_LCL_VAR);
+        }
+        else
+        {
+            addr->SetOper(GT_LCL_FLD);
+            addr->AsLclFld()->gtLclOffs  = 0;
+            addr->AsLclFld()->gtFieldSeq = FieldSeqStore::NotAField();
+
+            if (((addr->gtFlags & GTF_VAR_DEF) != 0) && (genTypeSize(simdType) < genTypeSize(lclType)))
+            {
+                addr->gtFlags |= GTF_VAR_USEASG;
+            }
+
+            comp->lvaSetVarDoNotEnregister(addr->AsLclFld()->GetLclNum() DEBUGARG(Compiler::DNER_LocalField));
+        }
+
         addr->gtType = simdType;
         use.ReplaceWith(comp, addr);
     }
diff --git a/src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_27405/GitHub_27405.cs b/src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_27405/GitHub_27405.cs
new file mode 100644 (file)
index 0000000..1b76993
--- /dev/null
@@ -0,0 +1,41 @@
+// 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.Numerics;
+using System.Runtime.CompilerServices;
+
+class Program
+{
+    static int Main()
+    {
+        Vector3 v3 = Test1(new Vector4(1, 2, 3, 4));
+        if (v3.X != 1 || v3.Y != 2 || v3.Z != 3)
+        {
+            return 42;
+        }
+
+        Vector4 v4 = Test2(new Vector4(1, 2, 3, 4), new Vector4(2, 1, 4, 3));
+        if (v4.X != 3 || v4.Y != 6 || v4.Z != 21 || v4.W != 0)
+        {
+            return 43;
+        }
+
+        return 100;
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
+    public static Vector3 Test1(Vector4 value)
+    {
+        return Unsafe.As<Vector4, Vector3>(ref value);
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
+    static Vector4 Test2(Vector4 a, Vector4 b)
+    {
+        Vector4 c = a + b;
+        Vector3 d = Unsafe.As<Vector4, Vector3>(ref c);
+        return a * new Vector4(d, 0);
+    }
+}
diff --git a/src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_27405/GitHub_27405.csproj b/src/coreclr/tests/src/JIT/Regression/JitBlue/GitHub_27405/GitHub_27405.csproj
new file mode 100644 (file)
index 0000000..f3e1cbd
--- /dev/null
@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+  </PropertyGroup>
+  <PropertyGroup>
+    <DebugType>None</DebugType>
+    <Optimize>True</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildProjectName).cs" />
+  </ItemGroup>
+</Project>