diff options
author | Carol Eidt <carol.eidt@microsoft.com> | 2019-03-13 14:26:51 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-13 14:26:51 -0700 |
commit | 5198ce8d7aa80786b1ca7502db5fcf8cf6f3ddce (patch) | |
tree | f30a0680c6bddf2147b70479568b720e62b6a8c2 /tests/src/JIT/Regression/JitBlue | |
parent | 52dc01aff1aeb1d972846706c65d7beb8ff9e1a7 (diff) | |
download | coreclr-5198ce8d7aa80786b1ca7502db5fcf8cf6f3ddce.tar.gz coreclr-5198ce8d7aa80786b1ca7502db5fcf8cf6f3ddce.tar.bz2 coreclr-5198ce8d7aa80786b1ca7502db5fcf8cf6f3ddce.zip |
Fix SIMD handle issues (#23193)
* Fix SIMD handle issues
PR #23052 was overly aggressive at applying the provided class handle (which defaults to NO_CLASS_HANDLE). In addition, make a small change to `SIMDIntrinsicWiden`, as it doesn't need to go through the complexity of inferring a class handle when it already exists on the node it's duplicating.
Fix #23159
Diffstat (limited to 'tests/src/JIT/Regression/JitBlue')
-rw-r--r-- | tests/src/JIT/Regression/JitBlue/GitHub_23159/GitHub_23159.cs | 150 | ||||
-rw-r--r-- | tests/src/JIT/Regression/JitBlue/GitHub_23159/GitHub_23159.csproj | 34 |
2 files changed, 184 insertions, 0 deletions
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23159/GitHub_23159.cs b/tests/src/JIT/Regression/JitBlue/GitHub_23159/GitHub_23159.cs new file mode 100644 index 0000000000..67f23cfa28 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23159/GitHub_23159.cs @@ -0,0 +1,150 @@ +// 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.Diagnostics; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; + +public static class GitHub_23159 +{ + static int Main(string[] args) + { + var str = "application/json,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7"; + var span = Encoding.ASCII.GetBytes(str).AsSpan(); + + if (BytesOrdinalEqualsStringAndAscii(str, span)) + { + return 100; + } + else + { + return -1; + } + } + + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + public unsafe static bool BytesOrdinalEqualsStringAndAscii(string previousValue, Span<byte> newValue) + { + // We just widen the bytes to char for comparision, if either the string or the bytes are not ascii + // this will result in non-equality, so we don't need to specifically test for non-ascii. + Debug.Assert(previousValue.Length == newValue.Length); + + // Use IntPtr values rather than int, to avoid unnessary 32 -> 64 movs on 64-bit. + // Unfortunately this means we also need to cast to byte* for comparisions as IntPtr doesn't + // support operator comparisions (e.g. <=, >, etc). + // Note: Pointer comparision is unsigned, so we use the compare pattern (offset + length <= count) + // rather than (offset <= count - length) which we'd do with signed comparision to avoid overflow. + var count = (IntPtr)newValue.Length; + var offset = (IntPtr)0; + + ref var bytes = ref MemoryMarshal.GetReference(newValue); + ref var str = ref MemoryMarshal.GetReference(previousValue.AsSpan()); + + do + { + // If Vector not-accelerated or remaining less than vector size + if (!Vector.IsHardwareAccelerated || (byte*)(offset + Vector<byte>.Count) > (byte*)count) + { + if (IntPtr.Size == 8) // Use Intrinsic switch for branch elimination + { + // 64-bit: Loop longs by default + while ((byte*)(offset + sizeof(long)) <= (byte*)count) + { + if (Unsafe.Add(ref str, offset) != (char)Unsafe.Add(ref bytes, offset) || + Unsafe.Add(ref str, offset + 1) != (char)Unsafe.Add(ref bytes, offset + 1) || + Unsafe.Add(ref str, offset + 2) != (char)Unsafe.Add(ref bytes, offset + 2) || + Unsafe.Add(ref str, offset + 3) != (char)Unsafe.Add(ref bytes, offset + 3) || + Unsafe.Add(ref str, offset + 4) != (char)Unsafe.Add(ref bytes, offset + 4) || + Unsafe.Add(ref str, offset + 5) != (char)Unsafe.Add(ref bytes, offset + 5) || + Unsafe.Add(ref str, offset + 6) != (char)Unsafe.Add(ref bytes, offset + 6) || + Unsafe.Add(ref str, offset + 7) != (char)Unsafe.Add(ref bytes, offset + 7)) + { + goto NotEqual; + } + + offset += sizeof(long); + } + if ((byte*)(offset + sizeof(int)) <= (byte*)count) + { + if (Unsafe.Add(ref str, offset) != (char)Unsafe.Add(ref bytes, offset) || + Unsafe.Add(ref str, offset + 1) != (char)Unsafe.Add(ref bytes, offset + 1) || + Unsafe.Add(ref str, offset + 2) != (char)Unsafe.Add(ref bytes, offset + 2) || + Unsafe.Add(ref str, offset + 3) != (char)Unsafe.Add(ref bytes, offset + 3)) + { + goto NotEqual; + } + + offset += sizeof(int); + } + } + else + { + // 32-bit: Loop ints by default + while ((byte*)(offset + sizeof(int)) <= (byte*)count) + { + if (Unsafe.Add(ref str, offset) != (char)Unsafe.Add(ref bytes, offset) || + Unsafe.Add(ref str, offset + 1) != (char)Unsafe.Add(ref bytes, offset + 1) || + Unsafe.Add(ref str, offset + 2) != (char)Unsafe.Add(ref bytes, offset + 2) || + Unsafe.Add(ref str, offset + 3) != (char)Unsafe.Add(ref bytes, offset + 3)) + { + goto NotEqual; + } + + offset += sizeof(int); + } + } + if ((byte*)(offset + sizeof(short)) <= (byte*)count) + { + if (Unsafe.Add(ref str, offset) != (char)Unsafe.Add(ref bytes, offset) || + Unsafe.Add(ref str, offset + 1) != (char)Unsafe.Add(ref bytes, offset + 1)) + { + goto NotEqual; + } + + offset += sizeof(short); + } + if ((byte*)offset < (byte*)count) + { + if (Unsafe.Add(ref str, offset) != (char)Unsafe.Add(ref bytes, offset)) + { + goto NotEqual; + } + } + + return true; + } + + // do/while as entry condition already checked + var AllTrue = new Vector<ushort>(ushort.MaxValue); + do + { + var vector = Unsafe.As<byte, Vector<byte>>(ref Unsafe.Add(ref bytes, offset)); + Vector.Widen(vector, out var vector0, out var vector1); + var compare0 = Unsafe.As<char, Vector<ushort>>(ref Unsafe.Add(ref str, offset)); + var compare1 = Unsafe.As<char, Vector<ushort>>(ref Unsafe.Add(ref str, offset + Vector<ushort>.Count)); + + if (!AllTrue.Equals( + Vector.BitwiseAnd( + Vector.Equals(compare0, vector0), + Vector.Equals(compare1, vector1)))) + { + goto NotEqual; + } + + offset += Vector<byte>.Count; + } while ((byte*)(offset + Vector<byte>.Count) <= (byte*)count); + + // Vector path done, loop back to do non-Vector + // If is a exact multiple of vector size, bail now + } while ((byte*)offset < (byte*)count); + + return true; + NotEqual: + return false; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23159/GitHub_23159.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_23159/GitHub_23159.csproj new file mode 100644 index 0000000000..7198ed8b5b --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_23159/GitHub_23159.csproj @@ -0,0 +1,34 @@ +<?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> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{2649FAFE-07BF-4F93-8120-BA9A69285ABB}</ProjectGuid> + <OutputType>Exe</OutputType> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir> + </PropertyGroup> + <!-- Default configurations to help VS understand the configurations --> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "></PropertyGroup> + <PropertyGroup> + <DebugType>None</DebugType> + <Optimize>True</Optimize> + <AllowUnsafeBlocks>True</AllowUnsafeBlocks> + </PropertyGroup> + <ItemGroup> + <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> + <Visible>False</Visible> + </CodeAnalysisDependentAssemblyPaths> + </ItemGroup> + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <ItemGroup> + <Compile Include="$(MSBuildProjectName).cs" /> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> + <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup> +</Project> |