From e2b42c53045dee35e8f318ded412c26614ce3445 Mon Sep 17 00:00:00 2001 From: Sergey Andreenko Date: Thu, 6 Aug 2020 16:08:09 -0700 Subject: [PATCH] import array access as OBJ for structs. (#40488) --- src/coreclr/src/jit/importer.cpp | 13 +- .../JitBlue/Runtime_40440/Runtime_40440.cs | 175 +++++++++++++++++++++ .../JitBlue/Runtime_40440/Runtime_40440.csproj | 12 ++ 3 files changed, 197 insertions(+), 3 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_40440/Runtime_40440.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_40440/Runtime_40440.csproj diff --git a/src/coreclr/src/jit/importer.cpp b/src/coreclr/src/jit/importer.cpp index 8d485e6..5e575d1 100644 --- a/src/coreclr/src/jit/importer.cpp +++ b/src/coreclr/src/jit/importer.cpp @@ -1392,8 +1392,8 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr, } else if (asgType == TYP_STRUCT) { - asgType = impNormStructType(structHnd); - src->gtType = asgType; + // It should already have the appropriate type. + assert(asgType == impNormStructType(structHnd)); } if ((dest == nullptr) && (destAddr->OperGet() == GT_ADDR)) { @@ -4886,7 +4886,14 @@ GenTree* Compiler::impArrayAccessIntrinsic( if (intrinsicID != CORINFO_INTRINSIC_Array_Address) { - arrElem = gtNewOperNode(GT_IND, elemType, arrElem); + if (varTypeIsStruct(elemType)) + { + arrElem = gtNewObjNode(sig->retTypeClass, arrElem); + } + else + { + arrElem = gtNewOperNode(GT_IND, elemType, arrElem); + } } if (intrinsicID == CORINFO_INTRINSIC_Array_Set) diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_40440/Runtime_40440.cs b/src/tests/JIT/Regression/JitBlue/Runtime_40440/Runtime_40440.cs new file mode 100644 index 0000000..000045a --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_40440/Runtime_40440.cs @@ -0,0 +1,175 @@ +// 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.Numerics; +using System.Runtime.CompilerServices; +using System.Diagnostics; +using System.Runtime.Intrinsics; +using System.Security.Cryptography; + +class Runtime_40440 +{ + [MethodImpl(MethodImplOptions.NoInlining)] + static bool UseArrayElementAsCallArgument(T[,,] a, T b) + { + return G(b, a[1, 2, 3]); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static bool G(T a, T b) + { + if (typeof(T) == typeof(Vector)) + { + return (Vector)(object)a == (Vector)(object)b; + } + else if (typeof(T) == typeof(Vector2)) + { + return (Vector2)(object)a == (Vector2)(object)b; + } + else if (typeof(T) == typeof(Vector3)) + { + return (Vector3)(object)a == (Vector3)(object)b; + } + else if (typeof(T) == typeof(Vector4)) + { + return (Vector4)(object)a == (Vector4)(object)b; + } + else if (typeof(T) == typeof(Vector64)) + { + return a.Equals(b); + } + else if (typeof(T) == typeof(SmallStruct)) + { + return a.Equals(b); + } + else if (typeof(T) == typeof(LargeStruct)) + { + return a.Equals(b); + } + return false; + } + + static bool CheckVectorFloat() + { + var v = new Vector[4, 4, 4]; + var e = new Vector(33f); + v[1, 2, 3] = e; + return UseArrayElementAsCallArgument(v, e); + } + static bool CheckVector2() + { + var v = new Vector2[4, 4, 4]; + var e = new Vector2(33f); + v[1, 2, 3] = e; + return UseArrayElementAsCallArgument(v, e); + } + + static bool CheckVector3() + { + var v = new Vector3[4, 4, 4]; + var e = new Vector3(33f); + v[1, 2, 3] = e; + return UseArrayElementAsCallArgument(v, e); + } + + static bool CheckVector4() + { + var v = new Vector3[4, 4, 4]; + var e = new Vector3(33f); + v[1, 2, 3] = e; + return UseArrayElementAsCallArgument(v, e); + } + + static bool CheckVector64() + { + var v = new Vector64[4, 4, 4]; + var e = Vector64.Create(33f); + v[1, 2, 3] = e; + return UseArrayElementAsCallArgument(v, e); + } + + struct SmallStruct + { + float f; + + public SmallStruct(float f) + { + this.f = f; + } + + public override bool Equals(object obj) + { + if (!(obj is SmallStruct)) + { + return false; + } + return f == ((SmallStruct)obj).f; + } + } + + static bool CheckSmallStruct() + { + var v = new SmallStruct[4, 4, 4]; + var e = new SmallStruct(33f); + v[1, 2, 3] = e; + return UseArrayElementAsCallArgument(v, e); + } + + struct LargeStruct + { + float f1; + float f2; + float f3; + float f4; + float f5; + + public LargeStruct(float f) + { + f1 = f; + f2 = f; + f3 = f; + f4 = f; + f5 = f; + } + + public override bool Equals(object obj) + { + if (!(obj is LargeStruct)) + { + return false; + } + LargeStruct s2 = (LargeStruct)obj; + return (f1 == s2.f1) && (f2 == s2.f2) && (f3 == s2.f3) && (f4 == s2.f4) && (f5 == s2.f5); + } + } + + static bool CheckBigStruct() + { + var v = new LargeStruct[4, 4, 4]; + var e = new LargeStruct(33f); + v[1, 2, 3] = e; + return UseArrayElementAsCallArgument(v, e); + } + + public static int Main() + { + bool f = true; + f &= CheckVectorFloat(); + Debug.Assert(f); + f &= CheckVector2(); + Debug.Assert(f); + f &= CheckVector3(); + Debug.Assert(f); + f &= CheckVector4(); + Debug.Assert(f); + f &= CheckVector64(); + Debug.Assert(f); + f &= CheckSmallStruct(); + Debug.Assert(f); + f &= CheckBigStruct(); + Debug.Assert(f); + + return f ? 100 : 0; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_40440/Runtime_40440.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_40440/Runtime_40440.csproj new file mode 100644 index 0000000..986494e --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_40440/Runtime_40440.csproj @@ -0,0 +1,12 @@ + + + Exe + + + + True + + + + + -- 2.7.4