From 3d4a1d5cea0ae71eed1482990ce6e575049829d8 Mon Sep 17 00:00:00 2001 From: Carol Eidt Date: Thu, 28 Mar 2019 11:23:10 -0700 Subject: Struct & SIMD improvements (#22255) * [WIP] Struct & SIMD improvements - Enable CSE of struct values when handle is available (and add code to get the handle of HW SIMD types) - Don't require block nodes for SIMD assignments - Don't set `GTF_GLOB_REF` on `GT_OBJ` if it is local - Set `lvRegStruct` on promoted SIMD fields - Add tests for #19910 (fixed with this PR) and #3539 & #19438 (fixed with #21314) - Additional cleanup Fix #19910 --- .../JitBlue/GitHub_19438/GitHub_19438.cs | 126 +++++++++++++++++++++ .../JitBlue/GitHub_19438/GitHub_19438.csproj | 17 +++ .../JitBlue/GitHub_19910/GitHub_19910.cs | 40 +++++++ .../JitBlue/GitHub_19910/GitHub_19910.csproj | 17 +++ .../Regression/JitBlue/GitHub_3539/GitHub_3539.cs | 62 ++++++++++ .../JitBlue/GitHub_3539/GitHub_3539.csproj | 18 +++ 6 files changed, 280 insertions(+) create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_19438/GitHub_19438.cs create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_19438/GitHub_19438.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_19910/GitHub_19910.cs create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_19910/GitHub_19910.csproj create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_3539/GitHub_3539.cs create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_3539/GitHub_3539.csproj (limited to 'tests/src/JIT') diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_19438/GitHub_19438.cs b/tests/src/JIT/Regression/JitBlue/GitHub_19438/GitHub_19438.cs new file mode 100644 index 0000000000..b57cae9548 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_19438/GitHub_19438.cs @@ -0,0 +1,126 @@ +// 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; +using System.Collections.Generic; +using System.Diagnostics; + +// This test executes the same computation on a wrapped Vector4 ('float4') and a +// (not wrapped) Vector4. The code should be similar. +// This was a perf regression issue, so this test is mostly useful for running +// asm diffs. + +namespace GitHub_19438 +{ + class Program + { + struct float4 + { + public Vector4 v; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float4(float _x, float _y, float _z, float _w) + { + v = new Vector4(_x, _y, _z, _w); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public float4(Vector4 _v) + { + v = _v; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float4 operator +(float4 a, float4 b) + { + return new float4(a.v + b.v); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float4 operator -(float4 a, float4 b) + { + return new float4(a.v - b.v); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float4 operator *(float4 a, float4 b) + { + return new float4(a.v * b.v); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float4 operator /(float4 a, float4 b) + { + return new float4(a.v / b.v); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override string ToString() + { + return v.ToString(); + } + } + + static int Main(string[] args) + { + const int iterationCount = 10; + const int itemCount = 1000000; + + long totalTaskTime = 0; + + // First, use a wrapped Vector4. + List items = new List(itemCount); + for (int iteration = 0; iteration < iterationCount; ++iteration) + { + var taskTimer = Stopwatch.StartNew(); + + for (int item = 0; item < itemCount; ++item) + { + float4 v0 = new float4(1.0f, 2.0f, 3.0f, 4.0f); + float4 v1 = new float4(5.0f, 6.0f, 7.0f, 8.0f); + float4 v2 = (v0 * v1) - (v1 / v0 + v1); + float4 v3 = (v2 * v0) - (v2 / v0 + v1); + + items.Add(v2 * v3); + } + + taskTimer.Stop(); + totalTaskTime += taskTimer.ElapsedMilliseconds; + + items.Clear(); + GC.Collect(); + } + Console.WriteLine("Wrapped Average Time: " + totalTaskTime / iterationCount + "ms"); + + // Now, a plain Vector4 + totalTaskTime = 0; + List items2 = new List(itemCount); + for (int iteration = 0; iteration < iterationCount; ++iteration) + { + var taskTimer = Stopwatch.StartNew(); + + for (int item = 0; item < itemCount; ++item) + { + Vector4 v0 = new Vector4(1.0f, 2.0f, 3.0f, 4.0f); + Vector4 v1 = new Vector4(5.0f, 6.0f, 7.0f, 8.0f); + Vector4 v2 = (v0 * v1) - (v1 / v0 + v1); + Vector4 v3 = (v2 * v0) - (v2 / v0 + v1); + + items2.Add(v2 * v3); + } + + taskTimer.Stop(); + totalTaskTime += taskTimer.ElapsedMilliseconds; + + items2.Clear(); + GC.Collect(); + } + Console.WriteLine("Vector4 Average Time: " + totalTaskTime / iterationCount + "ms"); + + return 100; + } + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_19438/GitHub_19438.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_19438/GitHub_19438.csproj new file mode 100644 index 0000000000..d86ed9f3d7 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_19438/GitHub_19438.csproj @@ -0,0 +1,17 @@ + + + + + Release + AnyCPU + $(MSBuildProjectName) + Exe + + True + + + + + + + \ No newline at end of file diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_19910/GitHub_19910.cs b/tests/src/JIT/Regression/JitBlue/GitHub_19910/GitHub_19910.cs new file mode 100644 index 0000000000..bb2d536bab --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_19910/GitHub_19910.cs @@ -0,0 +1,40 @@ +// 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.Intrinsics; +using System.Runtime.Intrinsics.X86; +using System.Runtime.CompilerServices; + +namespace GitHub_19910 +{ + class Program + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static void SwapNonGeneric(ref Vector128 a, ref Vector128 b) + { + Vector128 tmp = a; a = b; b = tmp; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int Main() + { + if (Sse2.IsSupported) + { + Vector128 a = Sse2.ConvertScalarToVector128UInt32(0xA); + Vector128 b = Sse2.ConvertScalarToVector128UInt32(0xB); + + Vector128 tmp = a; a = b; b = tmp; // in-place version + SwapNonGeneric(ref a, ref b); // inlined version + + if ((Sse2.ConvertToUInt32(a) != 0xA) || (Sse2.ConvertToUInt32(b) != 0xB)) + { + Console.WriteLine("A={0}, B={1}", Sse2.ConvertToUInt32(a), Sse2.ConvertToUInt32(b)); + return -1; + } + } + return 100; + } + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_19910/GitHub_19910.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_19910/GitHub_19910.csproj new file mode 100644 index 0000000000..d86ed9f3d7 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_19910/GitHub_19910.csproj @@ -0,0 +1,17 @@ + + + + + Release + AnyCPU + $(MSBuildProjectName) + Exe + + True + + + + + + + \ No newline at end of file diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_3539/GitHub_3539.cs b/tests/src/JIT/Regression/JitBlue/GitHub_3539/GitHub_3539.cs new file mode 100644 index 0000000000..8fc6c689b7 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_3539/GitHub_3539.cs @@ -0,0 +1,62 @@ +// 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; + +namespace GitHub_19910 + +{ + class Program + { + public struct Bgr { public byte B; public byte G; public byte R; } + + public class BasicReadWriteBenchmark + where T : struct + { + + // NOTE: This includes cost of stack alloc + [MethodImpl(MethodImplOptions.NoInlining)] + static public void ReadFromStack() + { + unsafe + { + void* stackPtr = stackalloc byte[Unsafe.SizeOf()]; + + var value = Unsafe.Read(stackPtr); + } + } + + // NOTE: This includes cost of stack alloc + [MethodImpl(MethodImplOptions.NoInlining)] + static public void WriteToStack() + { + unsafe + { + void* stackPtr = stackalloc byte[Unsafe.SizeOf()]; + + T value = default(T); + Unsafe.Write(stackPtr, value); + } + } + } + + public class BasicReadWriteBenchmarkBgr : BasicReadWriteBenchmark { } + + static int Main() + { + try + { + BasicReadWriteBenchmarkBgr.ReadFromStack(); + BasicReadWriteBenchmarkBgr.WriteToStack(); + } + catch (Exception e) + { + Console.WriteLine("Failed with Exception: " + e.Message); + return -1; + } + return 100; + } + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_3539/GitHub_3539.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_3539/GitHub_3539.csproj new file mode 100644 index 0000000000..fb6ae363eb --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_3539/GitHub_3539.csproj @@ -0,0 +1,18 @@ + + + + + Release + AnyCPU + $(MSBuildProjectName) + Exe + + True + True + + + + + + + -- cgit v1.2.3